题意:求m个x组成的数模k是否等于c
m<=10^10,k<=10000
分析:百度之星初赛第一场的题,这题我A了,我的做法是:把m%k位数直接模拟取模操作,因为k<=10000,所以复杂度并不高。虽然A了,但是后来想了想,这种方法是错的,比如样例:1 13 13 1,如果按照我的做法,13%13=0,0个1=0 0!=1 所以输出No。但是实际上应该输出Yes。可能是数据太水,被我碰巧过了吧。
看了大神的题解:http://blog.csdn.net/u012288458/article/details/51472661
原来这题是用快速幂来做,自己还是太菜了,做题不够啊!
第一种,裸的矩阵乘法,构造矩阵
{f(x,i),x}*{10 0}={f(x,i+1),x}
{1 1}
复杂度O(Tlog m)
<span style="font-size:14px;">#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> using namespace std; typedef long long ll; const int N=100000+9; int mod; struct Mat { int x,y; int m[3][3]; Mat operator*(Mat b) { Mat ans; memset(ans.m,0,sizeof(ans.m)); ans.x=x;ans.y=b.y; for(int i=1;i<=ans.x;i++) for(int j=1;j<=ans.y;j++) for(int k=1;k<=y;k++) ans.m[i][j]=(ans.m[i][j]+m[i][k]*b.m[k][j]%mod)%mod; return ans; } }; int main() { int T;scanf("%d",&T); int x,k,cc; ll m; for(int cas=1;cas<=T;cas++){ printf("Case #%d: ",cas); scanf("%d%lld%d%d",&x,&m,&k,&cc); mod=k; Mat a,b,c; a.x=1,a.y=2,a.m[1][1]=0,a.m[1][2]=x; b.x=b.y=2,b.m[1][1]=10,b.m[1][2]=0,b.m[2][1]=b.m[2][2]=1; c.x=c.y=2;c.m[1][1]=c.m[2][2]=1;c.m[1][2]=c.m[2][1]=0; for(;m;m>>=1){ if(m&1)c=c*b; b=b*b; } a=a*c; if(a.m[1][1]==cc)printf("Yes "); else printf("No "); } return 0; }</span>
还可以用循环节来做,因为是模k,取模后最多有k个数,循环节显然小于K
所以时间复杂度是O(k)
<span style="font-size:14px;">#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int T; int x,mod,c; int dep[10010]; long long m; int main() { scanf("%d",&T); for (int j=1;j<=T;j++) { scanf("%d%I64d%d%d",&x,&m,&mod,&c); printf("Case #%d: ",j); memset(dep,0,sizeof(dep)); int now=0,cnt=0; for (;m>0;) { now=(now*10+x)%mod;cnt++;m--; if (!dep[now]) dep[now]=cnt; else m%=(long long)(cnt-dep[now]); } if (now==c) printf("Yes "); else printf("No "); } return 0; }</span>