您的位置:首页 > 其它

hdu 5690 矩阵快速幂/循环节

2016-05-24 16:26 369 查看
题意:求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:\n",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\n");
else printf("No\n");
}
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:\n",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\n"); else printf("No\n");
}
return 0;
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: