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>
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>
相关文章推荐
- Python爬虫框架scrapy批量获取腾讯招聘网上面的信息
- Volley框架的基本解读(四)
- 《opencv3编程入门》代码(配合网盘视频,C语言)
- C中常用的字符串函数
- Hbase常用命令
- 定制班第4课 Spark Streaming 事务处理
- javascript中文网学习
- IOS照片颠倒分析及PHP服务端的处理
- repo 下载Android源码(国内镜像)
- 仿小米视频下滑视频动画效果
- wiki百科翻译之Lean software development之Eliminate waste
- iOS懒加载
- 203. Remove Linked List Elements
- Adb connection Error:远程主机强迫关闭了一个现有的连接
- requestAnimationFrame
- verilog串口接收多个数据进行处理的实现方法
- 第十二周—阅读程序(3)
- python pip源配置
- java实现爬取知乎用户基本信息
- java用POI设置Excel的列宽