CF859G,奇妙的数学题

来源:互联网 发布:淘宝店铺重开 编辑:程序博客网 时间:2024/05/16 19:35

当时赛场上A掉前三题后,跟Chenwystc大爷分头开DE,我D他E,然后因为我是先做分值更低的D,导致只有rk155,比rk119的Chenwystc大爷低到不知道哪里去了。
A掉E后还有44分钟,大力做G,根本做不出,我真是太菜了。
从物理学角度看这题,有一个显然的做法:直接判n个质点的重心是否在圆心即可。具体实现时若直接用单位根,精度会爆炸,毕竟题解里号称可以造出重心离圆心只有10500的数据。实际上经高人提醒,可以用模意义下的原根替代单位根,注意最好多取几个素数,因为模意义下正确性没有严格保障。
那么,为什么直接判n个质点的重心是否在圆心即可?
考虑将n个质点写成多项式n1i=0aixi,然后每次操作相当于减去形如1+x2+x4+x61+x3+x6+x9之类的多项式。
1+x2+x4+x6之类的多项式改写成xn1xd1=n1i=0(xωin)nd1i=0(xωidn)。其中d是n的因子
然后可以发现最大公因式就是n1i=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[N],w,x,y,z;char c[N];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;}