寺庙逃脱
2016-05-19 20:53
381 查看
题目大意
有q个询问,每个询问给出给出a[0]=k,和递推式
a[n]=A∗a[n−1]+BC∗a[n−1]+D
求a
mod p的值。
数据范围q<=104,n<=1018,p<=109,|A,B,C,D|<p,保证p为素数
矩阵乘法
a[n+1]=A∗a[n]+BC∗a[n]+D
考虑往下代入递推式a[n+1]=A∗A∗a[n−1]+BC∗a[n−1]+D+BC∗A∗a[n−1]+BC∗a[n−1]+D+D
分子分母同时乘上C*a[n-1]+D,于是a[n+1]=A∗(A∗a[n−1]+B)+B∗(C∗a[n−1]+D)C∗(A∗a[n−1]+B)+D∗(C∗a[n−1]+D)
提出a[n-1]a[n+1]=(A2+B∗C)∗a[n−1]+A∗B+B∗D(A∗C+D∗C)∗a[n−1]+B∗C+D2
容易发现A,B,C,D的转移矩阵是固定的。然后就可以用矩阵乘法加快速幂。
逆元就随意搞搞就行啦。
代码
我脑残打成了4*4的转移矩阵,其实2*2的就行了。#include<cstdio> #include<algorithm> #include<cstring> #define ll long long ll n,k,a,b,c,d,p; int read(ll &n){ char ch=getchar(); while((ch!='-')&&((ch<'0')||(ch>'9')))ch=getchar(); ll q=0,w=1;if(ch=='-')w=-1,ch=getchar(); while(ch>='0' && ch<='9')q=q*10+ch-48,ch=getchar();n=q*w; } struct ju{ ll w[5][5]; } f,g,one; ju operator *(ju a,ju b){ ju c; memset(c.w,0,sizeof(c.w)); for (int i=1;i<=4;i++) for (int k=1;k<=4;k++) for (int j=1;j<=4;j++) { c.w[i][k]=(c.w[i][k]+a.w[i][j]*b.w[j][k]%p)%p; } return c; } ll qss(ll x,ll y){ if (y==0) return 1; if (y==1) return x; ll s=qss(x,y/2);s=s*s%p; if (y%2==0) return s; s=s*x%p;return s; } ju qs(ju g,ll y){ if (y==0) return one; if (y==1) return g; ju c=qs(g,y/2);c=c*c; if (y%2==0) return c; c=c*g;return c; } int main(){ one.w[1][1]=one.w[2][2]=one.w[3][3]=one.w[4][4]=1; ll q;read(q); for (q=q;q>0;q--){ read(k);read(a);read(b);read(c);read(d);read(n);read(p); if (n==0){printf("%lld",k);continue;} a=(a+p)%p;b=(b+p)%p;c=(c+p)%p;d=(d+p)%p; memset(g.w,0,sizeof(g.w));memset(f.w,0,sizeof(f.w)); f.w[1][1]=a;f.w[1][2]=b;f.w[1][3]=c;f.w[1][4]=d; g.w[1][1]=a;g.w[1][2]=b;g.w[1][3]=g.w[2][1]=g.w[2][4]=c; g.w[2][2]=g.w[3][3]=g.w[4][4]=d; g=qs(g,n-1); f=f*g; ll s1=(f.w[1][1]*k+f.w[1][2])%p,s2=(f.w[1][3]*k+f.w[1][4])%p; s2=qss(s2,p-2); printf("%lld\n",s1*s2%p); } }
相关文章推荐
- JAVA设计模式(19):行为型-观察者模式(Observer)
- LINUX——查看操作系统/CPU/内存信息
- LinearEquations
- 卸载Openfire
- ZooKeeper:Quick Start
- Adam学习24之MarkDuplicatesSuite修改后有问题
- 【cocos2dx 3.3 lua】02 去掉调试信息以及多分辨率适配
- 从巴菲特10亿美元买苹果股 看“硬件公司”的低谷期
- MySQL服务无法启动 3534
- hdu 2256(矩阵快速幂)
- UVA550 Multiplying by Rotation
- 纸牌游戏
- Tornado异步IO
- java模拟接口回调
- HDU 5335 Walk Out
- UVA575 Skew Binary
- android:layout_weight 使用方法
- 万圣节派对
- 具有静态和动态生存期对象的时钟程序
- AngularJs $scope.$apply