• CF765G. Math, math everywhere


    题目大意

    给出长度为m的数组s和数字N,求多少个数k满足0<=k<N且对于每个i=0~m-1,都有gcd(k+i,N)=1当且仅当si=1

    m<=40,N以Πpi^ai的方式给出,n<=5e5

    题解

    先把01翻转变成在x%p=0的x处填1,填出来的显然按照Πpi为一个周期,所以只需要考虑ai=1的情况最后再乘上Πpi^(ai-1)即可

    数字k可以写成模pi的同余组,一个同余组唯一对应一个0~N-1中的数,否则存在<N的%pi=0的数,所以唯一对应

    问题变成统计同余组的情况,对于%p=q相当于在数组上按照间隔p的顺序跳着填,类似01010101或者01001001之类的

    于是对于p<=m的状压记忆化,>m的因为只会填最多一个所以可以只记录剩余个数dp

    发现当p以3或5开头的话状态很多,同时发现当p=29,31,37的时候很类似上面第二部分的dp,所以在做29,31,37的时候把前后m-p位状压中间的记录个数即可,<=23的记忆化,>40的记个数

    分三个部分dp,听起来很简单但是细节很多

    细节:

    1、记忆化23的时候如果用map存时间会炸掉(大概一千七百万多),所以在做23的时候直接转移到第二部分

    2、第二部分做29时如果直接循环复杂度为2^22*18*11,所以只做有值的部分,时间变成17000000*11

    3、做完29之后状态会增多,如果再按照上面的来搞状态就不止一千多万了,所以第二部分每做完之后都要缩成新的二进制状态

    4、缩完之后空间直接存会炸掉(2^22*41),所以要编号

    5、缩的时候新开的数组开2^18*23,开原来那么大也会炸掉

    code

    不知道有没有更简单的做法

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define low(x) ((x)&-(x))
    #define add(a,b) a=((a)+(b))%1000000007
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define mod 1000000007
    #define ll long long
    //#define file
    using namespace std;
    
    int g[79691777],G[6029313],h[41],num[1048576],m,n,M,MM,M2,MM2,id,id2,i,j,k,l,J,K,sum;
    ll p[500001],P[41],A,L,L2,L3,LL2,ans,Ans,s1,s2,S1,S2,S;
    char st[41];
    pair<ll,int> s;
    map<ll,int> f[13];
    map<ll,int> :: iterator I;
    
    ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
    int turn(int i,int j,int k,int M,int L2) {return (i*(L2+1)+j)*(M+1)+k;}
    ll get(ll t,int x,int y)
    {
    	int i,ans=0;
    	t>>=x;y-=x-1;
    	while (y)
    	{
    		if (y>20) ans+=num[t&(P[20]-1)],y-=20,t>>=20;
    		else {ans+=num[t&(P[y]-1)];break;}
    	}
    	return ans;
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF765G.in","r",stdin);
    	#endif
    	
    	P[0]=1;
    	fo(i,1,40) P[i]=P[i-1]*2;
    	scanf("%s",st+1);m=strlen(st+1);Ans=1;
    	scanf("%d",&n);
    	fo(i,1,n) scanf("%lld%lld",&p[i],&A),Ans=(Ans*qpower(p[i],A-1))%mod;
    	fd(i,m,1) s1=s1*2+(st[i]-'0'),sum+=!(st[i]-'0');
    	
    	l=(1ll<<20)-1;
    	fo(i,1,l) num[i]=num[i-low(i)]+1;
    	sort(p+1,p+n+1);
    	L=(1ll<<m)-1;s1^=L;
    	
    	if (p[1]<=23)
    	f[0][0]=1;
    	else
    	if (p[1]<m)
    	M=m-p[1],L2=P[M]-1,g[get(s1,M,p[1]-1)]=1;
    	else
    	h[sum]=1;
    	l=1;
    	
    	while (l<=n && p[l]<=23)
    	{
    		for (I=f[l-1].begin(); I!=f[l-1].end(); ++I)
    		{
    			s=*I;
    			for (i=S=0; i<m; i+=p[l]) S|=1ll<<i;
    			fo(j,0,p[l]-1)
    			{
    				s2=s.first|S;
    				if ((s2&s1)==s2)
    				{
    					if (l==n || p[l+1]>23)
    					{
    						if (l==n || p[l+1]>=m)
    						k=get(s2^s1,0,m-1),add(h[k],s.second);
    						else
    						{M=m-p[l+1];L2=P[M]-1;M2=p[l+1]-M;k=get(s2^s1,M,p[l+1]-1);add(g[turn(s2&(P[M]-1),s2>>p[l+1],k,M2,L2)],s.second);}
    					}
    					else
    					add(f[l][s2],s.second);
    				}
    				S=(S*2)&L;
    			}
    		}
    		++l;
    	}
    	if (!M && l<=n && p[l]<m) {printf("0
    ");return 0;}
    	while (l<=n && p[l]<m)
    	{
    		S=get(s1,M,p[l]-1);S1=s1&(P[M]-1),S2=s1>>p[l];
    		fd(i,L2,0)
    		{
    			fd(j,L2,0)
    			{
    				fo(k,0,M2)
    				{
    					id=turn(i,j,k,M2,L2);
    					if (g[id])
    					{
    						s2=g[id];g[id]=0;
    						if (l==n || p[l+1]>=m)
    						{
    							fo(J,0,M-1)
    							if ((s1&P[J]) && (s1&P[J+p[l]]))
    							K=num[(i|P[J])^S1]+num[(j|P[J])^S2]+k,add(h[K],s2);
    							if (k)
    							K=num[i^S1]+num[j^S2]+k-1,add(h[K],1ll*s2*k%mod);
    							K=num[i^S1]+num[j^S2]+k,add(h[K],1ll*s2*(S-k)%mod);
    						}
    						else
    						{
    							fo(J,0,M-1)
    							if ((s1&P[J]) && (s1&P[J+p[l]]))
    							add(g[turn(i|P[J],j|P[J],k,M2,L2)],s2);
    							if (k)
    							add(g[turn(i,j,k-1,M2,L2)],1ll*s2*k%mod);
    							add(g[turn(i,j,k,M2,L2)],1ll*s2*(S-k)%mod);
    						}
    					}
    				}
    			}
    		}
    		
    		++l;
    		if (l<=n && p[l]<m)
    		{
    			MM=m-p[l],LL2=P[MM]-1,MM2=p[l]-MM;
    			S1=get(s1,MM,M-1);S2=get(s1,p[l-1],p[l]-1);
    			fo(i,0,L2)
    			{
    				fo(j,0,L2)
    				{
    					fo(k,0,M2)
    					{
    						id=turn(i,j,k,M2,L2);
    						if (g[id])
    						{
    							id2=turn(i&(P[MM]-1),j>>(p[l]-p[l-1]),k+(S1-(num[i]-num[i&(P[MM]-1)]))+(S2-(num[j]-num[j>>(p[l]-p[l-1])])),MM2,LL2);
    							add(G[id2],g[id]);
    						}
    					}
    				}
    			}
    			memcpy(g,G,((LL2+1)*(LL2+1)*(MM2+1))*4);
    			M=MM,L2=LL2,M2=MM2;
    			memset(G,0,((L2+1)*(L2+1)*(M2+1))*4);
    		}
    	}
    	while (l<=n)
    	{
    		fo(i,0,m)
    		{
    			if (i)
    			add(h[i-1],1ll*h[i]*i%mod);
    			h[i]=1ll*h[i]*(p[l]-m+(sum-i))%mod;
    		}
    		++l;
    	}
    	
    	ans=h[0];
    	printf("%lld
    ",ans*Ans%mod);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    TP框架的小知识
    执行sql语句的注意事项
    关于引用值的总结
    几道经典容易错的php面试题
    Smarty模板的学习_2
    Smarty模板的学习_1
    数据库的权限操作
    redhat与zlib兼容性问题?
    Ubuntu中Qt Creator无法启动调试
    ubuntu下安装chrome浏览器和flash插件
  • 原文地址:https://www.cnblogs.com/gmh77/p/13610497.html
Copyright © 2020-2023  润新知