您的位置:首页 > 其它

CF859G,奇妙的数学题

2017-09-23 22:58 155 查看
当时赛场上A掉前三题后,跟Chenwystc大爷分头开DE,我D他E,然后因为我是先做分值更低的D,导致只有rk155,比rk119的Chenwystc大爷低到不知道哪里去了。

A掉E后还有44分钟,大力做G,根本做不出,我真是太菜了。

从物理学角度看这题,有一个显然的做法:直接判n个质点的重心是否在圆心即可。具体实现时若直接用单位根,精度会爆炸,毕竟题解里号称可以造出重心离圆心只有10−500的数据。实际上经高人提醒,可以用模意义下的原根替代单位根,注意最好多取几个素数,因为模意义下正确性没有严格保障。

那么,为什么直接判n个质点的重心是否在圆心即可?

考虑将n个质点写成多项式∑n−1i=0aixi,然后每次操作相当于减去形如1+x2+x4+x6或1+x3+x6+x9之类的多项式。

将1+x2+x4+x6之类的多项式改写成xn−1xd−1=∏n−1i=0(x−ωin)∏nd−1i=0(x−ωidn)。其中d是n的因子

然后可以发现最大公因式就是∏n−1i=0[gcd(i,n)==1](x−ωin),即n次分圆多项式。

分圆多项式是不可约的整系数多项式,这是其性质。

本来是要做多项式取模的,但实际上只要任取一个ωdn(其中gcd(n,d)==1)带入原多项式计算即可,这就得到了开头的结论。

对此的感性理解是因为分圆多项式是不可约的整系数多项式,所以如果一个ωdn满足,那么一定要把剩下的所有ωin也配上,这才能凑成整系数多项式。

毕竟我也不是搞MO的,严格证明可能需要初三就拿到MO联赛一等的royms大爷了。

这是OI,不是MO,大胆猜想,不用证明,反对科学,崇尚迷信

#include<cstdio>
#include<ctime>
const int N=100005;
int n,i,p,g,a
,w,x,y,z;
char c
;
inline bool isp(int p){
for(register int i=2;i*i<=p;++i)if(p%i==0)return 0;
return 1;
}
inline int pow(int x,int y,int p){
int ans=1;
for(;y;y>>=1,x=1ll*x*x%p)if(y&1)ans=1ll*ans*x%p;return ans;
}
inline int getg(int p){
register int g=2,i;
for(;;++g){
for(i=1;i<=w;++i)
if(pow(g,a[i],p)==1)break;
if(i>w)return g;
}
}
int main(){
scanf("%d%s",&n,c+1);
for(i=1;i<=n;++i)c[i]^=48;p=1;
while(clock()<800){
for(p+=n;!isp(p);p+=n);
w=0;
for(i=2;i*i<=p-1;++i)if((p-1)%i==0)a[++w]=i,a[++w]=(p-1)/i;
g=getg(p);
z=pow(g,(p-1)/n,p);
for(i=x=1,y=0;i<=n;++i,x=1ll*x*z%p)
y=(y+1ll*x*c[i])%p;
if(y)return puts("NO"),0;
}
puts("YES");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: