CF859G,奇妙的数学题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值