zoukankan      html  css  js  c++  java
  • 【LOJ6436】【PKUSC2018】神仙的游戏(NTT)

    【LOJ6436】【PKUSC2018】神仙的游戏(NTT)

    题面

    LOJ

    题解

    看到(zsy)(PKUSC)回来就秒掉了这种神仙题
    吓得我也赶快看了看(PKUSC)都有些什么神仙题
    然后就找到了这样一道神仙题

    考虑一个奇怪的暴力:
    我们只需要对于(0/1)进行匹配
    如果出现了(0/1)匹配的情况,那么当前长度一定不能构成(border)
    的确,这样子肯定是对的,
    但是我们似乎有一些奇怪的情况没有考虑清楚
    如果两个串出现了交集,似乎不能构成(border)的情况就会增加诶

    这样考虑很不清楚,我们从另外一个角度考虑(border)
    如果存在长度为(len)(border)
    我们把字符串按照位置对于(n-len)的余数分类
    显然在同一类中的所有字符都要一样。
    证明?画下图就清楚了。
    现在有了这个结论,我们再来考虑这个问题。
    我们要检查一个长度为(len)(border)是否存在
    只需要检查是否出现了分组之后不满足同组相同的情况
    现在只需要把串翻转,然后将正反两个串的分别以(0/1)来构建生成函数
    做个卷积(check)一下就好了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MOD 998244353
    #define MAX 3000000
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    ll ans;
    int N,n,l;
    int r[MAX],W[MAX],A[MAX],B[MAX],s[MAX];
    char c[MAX];
    int fpow(int a,int b)
    {
    	int s=1;
    	while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
    	return s;
    }
    void NTT(int *P,int opt)
    {
    	for(int i=1;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
    	for(int i=1;i<N;i<<=1)
    	{
    		int w=fpow(3,(MOD-1)/(i<<1));W[0]=1;
    		for(int k=1;k<i;++k)W[k]=1ll*W[k-1]*w%MOD;
    		for(int p=i<<1,j=0;j<N;j+=p)
    			for(int k=0;k<i;++k)
    			{
    				int X=P[j+k],Y=1ll*P[i+j+k]*W[k]%MOD;
    				P[j+k]=(X+Y)%MOD;P[i+j+k]=(X+MOD-Y)%MOD;
    			}
    	}
    	if(opt==-1)
    	{
    		reverse(&P[1],&P[N]);
    		for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
    	}
    
    }
    int main()
    {
    	scanf("%s",c);
    	n=strlen(c);
    	for(N=1;N<n+n;N<<=1)++l;
    	for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	for(int i=0;i<n;++i)A[i]=c[i]=='0',B[i]=c[n-i-1]=='1';
    	NTT(A,1);NTT(B,1);
    	for(int i=0;i<N;++i)A[i]=1ll*A[i]*B[i]%MOD;
    	NTT(A,-1);
    	ans=1ll*n*n;
    	for(int i=1;i<n;++i)
    	{
    		ans^=1ll*(n-i)*(n-i);
    		for(int j=i;j<n;j+=i)
    			if(A[n-j-1]||A[n+j-1]){ans^=1ll*(n-i)*(n-i);break;}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Android 查看APK文件的签名算法
    Android 查看App冷启动时间/热启动时间/页面打开时间
    Android 查看Apk签名方式V1和V2
    Android App启动速度优化
    Android SharedPreferences中apply和commit的效率差距
    Gralde 网络代理
    Git 将子文件夹分离为一个新的库
    Fabric-Crashlytics-Android 注意点
    Gradle编译失败 generating the main dex list
    Gralde 同步失败
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9151844.html
Copyright © 2011-2022 走看看