bzoj3240: [Noi2013]矩阵游戏(矩阵乘法+快速幂)
2017-10-27 16:19
399 查看
题目传送门
费马小定理是什么鬼。。
解法:
这道题其实就是把n行的数排成一行。
后面的数由前面的数得到。
用矩乘啊。
加个快速幂呗。
看了下数据范围。。。
n*m有10^2000000,快速幂怎么也得一千万啊,加个高精度除2,炸炸炸。
问了一下lxj大佬。
大佬说:用费马小定理啊!
怒查一波费马,还有这种操作?!
a^(p-1) mod p=1
题目都要mod 1,000,000,007。
所以根据费马小定理我们把质数都膜个1,000,000,006就好了。
矩阵蛮好想的。
分两种矩阵,一种是每一行中间往后推一个:
a 0
b 1
每一行转移m-1次
一种是每一行最后一个到下一行第一个:
c 0
d 1
整个矩阵转移n-1次
然后就快速幂就完了。
先搞出一行的转移矩阵。
再搞出n行的转移矩阵。
然后我开心的错了三次。
实在不行上网看了看题解。
题解说:
在指数膜1,000,000,006的时候,如果a=c=1的话,要膜 1,000,000,007
还有这种操作?!我的三次提交。。
代码实现:
费马小定理是什么鬼。。
解法:
这道题其实就是把n行的数排成一行。
后面的数由前面的数得到。
用矩乘啊。
加个快速幂呗。
看了下数据范围。。。
n*m有10^2000000,快速幂怎么也得一千万啊,加个高精度除2,炸炸炸。
问了一下lxj大佬。
大佬说:用费马小定理啊!
怒查一波费马,还有这种操作?!
a^(p-1) mod p=1
题目都要mod 1,000,000,007。
所以根据费马小定理我们把质数都膜个1,000,000,006就好了。
矩阵蛮好想的。
分两种矩阵,一种是每一行中间往后推一个:
a 0
b 1
每一行转移m-1次
一种是每一行最后一个到下一行第一个:
c 0
d 1
整个矩阵转移n-1次
然后就快速幂就完了。
先搞出一行的转移矩阵。
再搞出n行的转移矩阵。
然后我开心的错了三次。
实在不行上网看了看题解。
题解说:
在指数膜1,000,000,006的时候,如果a=c=1的话,要膜 1,000,000,007
还有这种操作?!我的三次提交。。
代码实现:
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int mod=1000000007; char ss[1100000]; ll a[1100000],b[1100000]; struct node { ll a[3][3]; node() { memset(a,0,sizeof(a)); } }A,B,ans; node jc(node a,node b) { node c; for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) for(int k=1;k<=2;k++) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod; return c; } int main() { //freopen("3240.in","r",stdin); //freopen("3240.out","w",stdout); scanf("%s",ss+1); int len1=strlen(ss+1); for(int i=1;i<=len1;i++) a[i]=ss[i]-'0'; scanf("%s",ss+1); int len2=strlen(ss+1); for(int i=1;i<=len2;i++) b[i]=ss[i]-'0'; ll aa,bb,c,d;scanf("%lld%lld%lld%lld",&aa,&bb,&c,&d); ll resta=0;int t=1; ll moda=mod; if(!(aa==1&&c==1)) moda--; while(resta<moda&&t<=len1) { resta=resta*10+a[t];t++; } while(t<=len1) { resta%=moda; resta=resta*10+a[t];t++; } resta--;resta=(resta+moda)%moda; ll restb=0;t=1; while(restb<moda&&t<=len2) { restb=restb*10+b[t];t++; } while(t<=len2) { restb%=moda; restb=restb*10+b[t];t++; } restb--;restb=(restb+moda)%moda; A.a[1][1]=aa; A.a[2][1]=bb;A.a[2][2]=1; B.a[1][1]=c; B.a[2][1]=d;B.a[2][2]=1; node ans1; for(int i=1;i<=2;i++) ans1.a[i][i]=1; while(restb!=0) { if(restb%2==1) ans1=jc(ans1,A); A=jc(A,A);restb/=2; } ans=jc(ans1,B); node s; for(int i=1;i<=2;i++) s.a[i][i]=1; while(resta!=0) { if(resta%2==1) s=jc(s,ans); ans=jc(ans,ans);resta/=2; } s=jc(s,ans1); printf("%lld\n",(s.a[1][1]+s.a[2][1])%mod); return 0; }
相关文章推荐
- BZOJ 3240 [Noi2013] 矩阵游戏 题解
- bzoj3240: [Noi2013]矩阵游戏
- bzoj 3240: [Noi2013]矩阵游戏
- bzoj 3240 [Noi2013]矩阵游戏
- BZOJ 3240: [Noi2013]矩阵游戏 矩阵乘法 费马小定理
- BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)
- (十进制高速幂+矩阵优化)BZOJ 3240 3240: [Noi2013]矩阵游戏
- [BZOJ3240][NOI2013]矩阵游戏(数论+矩乘)
- [BZOJ 3240][NOI 2013]矩阵游戏(数学+乘法逆元)
- BZOJ 3240 [Noi2013]矩阵游戏 ——费马小定理 快速幂
- BZOJ 3240: [Noi2013]矩阵游戏
- 【BZOJ3240】【UOJ124】【NOI2013】矩阵游戏
- bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化
- [BZOJ3240][NOI2013]矩阵游戏
- BZOJ3240 [Noi2013]矩阵游戏
- [BZOJ 3240][Noi2013]矩阵游戏:逆元+递推
- 【费马小定理+快速幂+逆元】BZOJ3240-[NOI2013]矩阵游戏
- bzoj 3240: [Noi2013]矩阵游戏
- BZOJ 3240 [NOI2013 D2T1] 矩阵游戏
- 【BZOJ】【3240】【NOI2013】矩阵游戏