快速幂与矩阵乘法
快速幂 算法的时间复杂度推导:n/2^k=1 => n=2^k => logn=log2^k => k=logn 故 O(logn) .2018-9-17 22:28
P1226 【模板】快速幂||取余运算
在线测评地址:https://www.luogu.org/problemnew/show/P1226
AC代码如下:
//P1226 【模板】快速幂||取余运算
//https://www.luogu.org/problemnew/show/P1226
//提交,测试点7,WA
//https://www.luogu.org/discuss/show?postid=56034看了讨论,发现
//输入:1 0 1 正确输出:1^0 mod 1=0 你的输出:1^0 mod 1=1
//总而言之,对洛谷加强数据(测试点7)表示不满,有些牛角尖了。2018-9-17 22:52
//将printf("%lld^%lld mod %lld=%lld\n",b,p,k,quick_power(b,p,k));改成
//printf("%lld^%lld mod %lld=%lld\n",b,p,k,quick_power(b,p,k)%k);
//提交AC。2018-9-17 22:53
#include <stdio.h>
#define LL long long
LL quick_power(LL b,LL p,LL k){
LL ans=1;
while(p){
if(p&1)ans=ans*b%k;
b=b*b%k;
p>>=1;
}
return ans;
}
int main(){
LL b,p,k;
scanf("%lld%lld%lld",&b,&p,&k);
printf("%lld^%lld mod %lld=%lld\n",b,p,k,quick_power(b,p,k)%k);
return 0;
}
//P1965 转圈游戏
//在线测评地址https://www.luogu.org/problemnew/show/P1965
//动笔,模拟,举个比样例更简单的例子,发现如下规律
//x1=(x0+m)%n
//x2=(x1+m)%n => x2=(x0+2m)%n
//x3=(x3+m)%n => x3=(x0+3m)%n
//xq=(x0+qm)%n => xq=(x0+qm%n)%n => xq=(x0+q%n*m)%q
//q=10^k 10^109 采用 快速幂 算法的时间复杂度 log(10^10^9) 大致 10^9 还是有些险
//快速幂,稳妥起见,不采用int 采用long long
//样例通过,一次成功,提交AC。2018-9-21
#include <stdio.h>
#define LL long long
LL quickPower(LL a,LL b,LL p){
LL ans=1;
while(b){
if(b&1)ans=(ans*a)%p;
a=(a*a)%p;
b>>=1;
}
return ans;
}
int main(){
LL n,m,k,x,ans;
scanf("%lld%lld%lld%lld",&n,&m,&k,&x);//此处写成 scanf("%d%d%d%d",&n,&m,&k,&x);
ans=quickPower(10,k,n);
ans=(x+ans*m)%n;
printf("%lld\n",ans);
return 0;
}
矩阵乘法
//P3390 【模板】矩阵快速幂
//在线测评地址https://www.luogu.org/problemnew/show/P3390
//提交,有些担心,但看到,测试点2-9 AC了,总算放下些心。测试点1,10卡住了
//代码没做任何修改,再次提交,竟然AC了。够神奇的。2018-9-18 19:48
#include <stdio.h>
#include <string.h>
#define LL long long
#define maxn 110
#define mod 1000000007
LL a[maxn][maxn],f[maxn][maxn],c[maxn][maxn],n,k;
void mul(){//此处写成 void mul(LL f[][],LL a[][])
LL i,j,k;
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
c[i][j]=(c[i][j]+a[i][k]*f[k][j])%mod;
memcpy(f,c,sizeof(c));
}
void mulself(){//此处写成 void mulself(LL a[][])
LL i,j,k;
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
memcpy(a,c,sizeof(c));
}
void quick_power(){//此处写成 void quick_power(LL a[][],LL k)
while(k){
if(k&1)mul();
mulself();
k>>=1;
}
}
int main(){
LL i,j;
scanf("%lld%lld",&n,&k);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%lld",&a[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
f[i][j]=1;//初始化为单位矩阵// 忘记了 初始化
else
f[i][j]=0;
quick_power();
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
printf("%lld ",f[i][j]);
printf("\n");
}
return 0;
}
//P1962 斐波那契数列
//在线测评地址https://www.luogu.org/problemnew/show/P1962
//[{f[2],f[1]}]*[{1,1},{1,0}] 与 [{1,1},{1,0}]*[{f[2]},{f[1]}] 从易算角度 选择后者
//该题要注意,数组的处理,起始选 0脚标开始 还是 1脚标开始,要特别注意。 2018-9-21
#include <stdio.h>
#include <string.h>
#define mod 1000000007
#define LL long long
LL f[2]={1,1},g[2],a[2][2]={{1,1},{1,0}},d[2][2]={{1,0},{0,1}},c[2][2],n;//d 此刻 单位矩阵
void mul(){//a*d
LL i,j,k;
memset(c,0,sizeof(c));
for(i=0;i<2;i++)//此处写成 for(i=1;i<=2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
c[i][j]=(c[i][j]+a[i][k]*d[k][j])%mod;
memcpy(d,c,sizeof(c));
}
void mulself(){//a*a
LL i,j,k;
memset(c,0,sizeof(c));
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
memcpy(a,c,sizeof(c));
}
void quickPower(LL b){
while(b){
if(b&1)mul();
mulself();
b>>=1;
}
}
void mulf(){
LL i,j;
memset(g,0,sizeof(g));
for(i=0;i<2;i++)
for(j=0;j<2;j++)
g[i]=(g[i]+d[i][j]*f[j])%mod;
memcpy(f,g,sizeof(g));
}
int main(){
scanf("%lld",&n);
if(n==1||n==2)printf("1\n");//特判
else{
quickPower(n-2);
mulf();
printf("%lld\n",f[0]);
}
return 0;
}
//P1067 Warcraft III 守望者的烦恼
//决定重写该题代码,重新设计矩阵,以下内容为重新设计。2018-9-22 16:07
//在线测评地址https://vijos.org/p/1067
//若有该题(1190:上台阶,在线测评地址http://ybt.ssoier.cn:8088/problem_show.php?pid=1190)基础,此题的递推公式不成问题。
//该题递推公式:f(n)=f(n-1)+f(n-2)+...+f(n-k)
//f(0)=1,f(1)=1,f(2)=f(2-1)+f(2-2),f(3)=f(3-1)+f(3-2)+f(3-3),f(4)=f(4-1)+f(4-2)+f(4-3)+f(4-4)
//f(k)=f(k-1)+f(k-2)+...+f(k-k)
//注意:f(1),f(2),...,f(k-1),f(k),通过两重循环可求得
//f(k+1)=f(k)+f(k-1)+...+f(1)
//f(k+2)=f(k+1)+f(k)+...+f(2)
//f(k+1),f(k+2),...,f(n-1),f(n)需通过矩阵乘法,才可快速求得
//0 1 0...0 0 0
//0 0 1...0 0 0
//... ... ...
//0 0 0...0 0 1
//1 1 ... 1 1 1
//构造 k 阶矩阵A如上?
//A*[f(1),f(2),...,f(k-1),f(k)]=[f(2),f(3),...,f(k),f(1)+f(2)+...+f(k-1)+f(k)]=[f(2),f(3),...,f(k),f(k+1)];
//故A^(n-k)*[f(1),f(2),...,f(k-1),f(k)]=[f(n-k),...,f(n-1),f(n)]
//编写完毕,样例测试后,提交,一把AC。相当满意目前矩阵的构造方法。2018-9-22 16:29
#include <stdio.h>
#include <string.h>
#define mod 7777777
#define LL long long
LL k,n,A[15][15],c[15][15],f[15],g[15];
void mul(){
LL i,j;
memset(g,0,sizeof(g));
for(i=1;i<=k;i++)
for(j=1;j<=k;j++)
g[i]=(g[i]+A[i][j]*f[j])%mod;
memcpy(f,g,sizeof(g));
}
void mulself(){
LL i,j,p;
memset(c,0,sizeof(c));
for(i=1;i<=k;i++)
for(j=1;j<=k;j++)
for(p=1;p<=k;p++)
c[i][j]=(c[i][j]+A[i][p]*A[p][j])%mod;
memcpy(A,c,sizeof(c));
}
void quickPower(LL b){
while(b){
if(b&1)mul();
mulself();
b>>=1;
}
}
int main(){
LL i,j;
memset(A,0,sizeof(A));
memset(f,0,sizeof(f));
scanf("%lld%lld",&k,&n);
for(j=1;j<=k;j++)A[k][j]=1;
for(i=1;i<=k-1;i++)A[i][i+1]=1;
f[1]=f[0]=1;
for(i=2;i<=k;i++)
for(j=0;j<i;j++)
f[i]=(f[i]+f[j])%mod;
if(n<=k)printf("%lld\n",f[n]);
else{
quickPower(n-k);
printf("%lld\n",f[k]);
}
return 0;
}
//P1067 Warcraft III 守望者的烦恼
//在线测评地址https://vijos.org/p/1067
//若有该题(1190:上台阶,在线测评地址http://ybt.ssoier.cn:8088/problem_show.php?pid=1190)基础,此题的递推公式不成问题。
//该题递推公式:f(n)=f(n-1)+f(n-2)+...+f(n-k)
//f(0)=1,f(1)=1,f(2)=f(2-1)+f(2-2),f(3)=f(3-1)+f(3-2)+f(3-3),f(4)=f(4-1)+f(4-2)+f(4-3)+f(4-4)
//f(k)=f(k-1)+f(k-2)+...+f(k-k)
//注意:f(1),f(2),...,f(k-1),f(k),通过两重循环可求得
//f(k+1)=f(k)+f(k-1)+...+f(1)
//f(k+2)=f(k+1)+f(k)+...+f(2)
//f(k+1),f(k+2),...,f(n-1),f(n)需通过矩阵乘法,才可快速求得
//1 1 ... 1 1
//1 0 ... 0 0
//0 1 ... 0 0
//... ... ...
//0 0 ... 1 0
//构造 k 阶矩阵A如上
//A*[f(k),f(k-1),...,f(1)]=[f(k)+f(k-1)+...+f(1),f(k),...,f(2)]=[f(k+1),f(k),...,f(2)];
//故A^(n-k)*[f(k),f(k-1),...,f(1)]=[f(n),f(n-1),...,f(n-k)]
//提交,测试点3,4AC,测试点2 Wrong Answer,其余测试点 Runtime Error
//修改,for(i=2;i<=k;i++)//此处写成 for(i=2;i<=n;i++),提交,只剩测试点2 Wrong Answer。
//查了讨论,发现 WA#2了的自己测k=n的吧...。
//继续修改,printf("%lld\n",f[k-n+1]);//此处写成 printf("%lld\n",f[n]);提交AC。
//感觉程序在矩阵的元素顺序上挺别扭,还是要改改的。 2018-9-22 13:26
//该种构造的矩阵,编写程序容易出错,难以一次AC,决定重新构造矩阵,重新编写代码,详见上面的方法。2018-9-22 15:35
#include <stdio.h>
#include <string.h>
#define mod 7777777
#define LL long long
LL k,n,f[15],g[15],A[15][15],c[15][15];
void mulself(){
LL i,j,p;
memset(c,0,sizeof(c));
for(i=1;i<=k;i++)
for(j=1;j<=k;j++)
for(p=1;p<=k;p++)
c[i][j]=(c[i][j]+A[i][p]*A[p][j])%mod;
memcpy(A,c,sizeof(c));
}
void mul(){
LL i,j;
memset(g,0,sizeof(g));
for(i=1;i<=k;i++)
for(j=1;j<=k;j++)
g[i]=(g[i]+A[i][j]*f[j])%mod;
memcpy(f,g,sizeof(g));
}
void quickPower(LL b){
while(b){
if(b&1)mul();
mulself();
b>>=1;
}
}
int main(){
LL i,j;
memset(f,0,sizeof(f));
memset(A,0,sizeof(A));
memset(g,0,sizeof(g));
scanf("%lld%lld",&k,&n);
g[1]=g[0]=1;
for(i=2;i<=k;i++)//此处写成 for(i=2;i<=n;i++)
for(j=0;j<i;j++)
g[i]=(g[i]+g[j])%mod;//f[i]初始化
for(i=1;i<=k;i++)f[i]=g[k-i+1];
for(j=1;j<=k;j++)A[1][j]=1;
for(i=2;i<=k;i++)A[i][i-1]=1;//此处写成A[i][i+1]=1,不过马上在接下来的测试中发现了//A[i][j]初始化
if(n<=k)printf("%lld\n",f[k-n+1]);//此处写成 printf("%lld\n",f[n]);
else{
quickPower(n-k);
printf("%lld\n",f[1]);
}
return 0;
}
//Matrix Power Series
//在线测评地址https://vjudge.net/problem/POJ-3233
//构造矩阵B如下:
//[A A]
//[0 I]
//计算n次方
//目前看来,矩阵初始化会麻烦些。
//在 B[i][j]=1;//此处写成B[i][j]=1;漏了if,误以为单位矩阵是全1,查了10分钟 花了些时间
//样例通过,提交AC。2018-9-22 22:28
#include <stdio.h>
#include <string.h>
#define LL long long
LL n,k,m,B[100][100],c[100][100],F[100][100];
void mul(){
LL i,j,p;
memset(c,0,sizeof(c));
for(i=1;i<=2*n;i++)
for(j=1;j<=2*n;j++)
for(p=1;p<=2*n;p++)
c[i][j]=(c[i][j]+B[i][p]*F[p][j])%m;
memcpy(F,c,sizeof(c));
}
void mulself(){
LL i,j,p;
memset(c,0,sizeof(c));
for(i=1;i<=2*n;i++)
for(j=1;j<=2*n;j++)
for(p=1;p<=2*n;p++)
c[i][j]=(c[i][j]+B[i][p]*B[p][j])%m;
memcpy(B,c,sizeof(c));
}
void quickPower(){
LL i,j;
while(k){
if(k&1)mul();
mulself();
k>>=1;
}
}
int main(){
LL i,j,a;
memset(B,0,sizeof(B));
memset(F,0,sizeof(F));
scanf("%lld%lld%lld",&n,&k,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
scanf("%lld",&a);
B[i][j+n]=B[i][j]=a;
}
for(i=n+1;i<=2*n;i++)
for(j=n+1;j<=2*n;j++)
if(i==j)
B[i][j]=1;//此处写成B[i][j]=1;漏了if,误以为单位矩阵是全1,查了10分钟
for(i=1;i<=2*n;i++)
for(j=1;j<=2*n;j++)
if(i==j)F[i][j]=1;//单位矩阵
quickPower();
for(i=1;i<=n;i++){
for(j=n+1;j<=2*n;j++)
printf("%lld ",F[i][j]);
printf("\n");
}
return 0;
}
//BZOJ4547 Hdu5171 小奇的集合
//GTY's birthday gift HDU - 5171
//在线测评地址https://vjudge.net/problem/HDU-5171
//基本思路,排序+矩阵乘法。
//决定还是要学习C++中sort用法。
//样例数据模拟如下
//6 3 2
//9 6 3 2
//15 9 6 3 2 和即为 35
//[1,1,1]
//[0,1,1]*[ans,a[1],a[2]]
//[0,1,0]
//样例通过,提交Wrong Answer
//修改 ans=(ans+a[i])%mod;//此处写成ans+=a[i],造成Wrong Answer 提交,Wrong Answer
//多次排查程序无果,翻阅网络中的代码,再反复读题,发现“Multi test cases (about 3)”
//有多组测试样例,而本人的代码只有一组样例,马上修改。while(scanf("%lld%lld",&n,&k)!=EOF){//一开始,没有写成循环的形式
//提交,Wrong Answer.
//翻看网络中的代码,发现问题出在ans初始化上。 //此处写成 LL i,ans=0; LL i,ans=0;//移到循环内。
//提交,AC。总结,测试时,同一个测试文件中一定要有多组数据,初始化问题就容易看出。2018-9-23 22:49
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define mod 10000007
using namespace std;
LL a[100100],n,k,g[4],c[4][4];
int cmp(LL a,LL b){
return a>b;//降序排列
}
void mulself(LL A[4][4]){
LL i,j,p;
memset(c,0,sizeof(c));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
for(p=1;p<=3;p++)
c[i][j]=(c[i][j]+A[i][p]*A[p][j])%mod;
memcpy(A,c,sizeof(c));
}
void mul(LL A[4][4],LL B[4][4]){
LL i,j,p;
memset(c,0,sizeof(c));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
for(p=1;p<=3;p++)
c[i][j]=(c[i][j]+A[i][p]*B[p][j])%mod;
memcpy(B,c,sizeof(c));
}
void mulf(LL B[4][4],LL f[4]){
LL i,j;
memset(g,0,sizeof(g));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
g[i]=(g[i]+B[i][j]*f[j])%mod;
memcpy(f,g,sizeof(g));
}
void quickPower(LL A[4][4],LL B[4][4]){
while(k){
if(k&1)mul(A,B);
mulself(A);
k>>=1;
}
}
int main(){
//此处写成 LL i,ans=0;
while(scanf("%lld%lld",&n,&k)!=EOF){//一开始,没有写成循环的形式
LL i,ans=0;//移到循环内。
LL A[4][4]={{0,0,0,0},{0,1,1,1},{0,0,1,1},{0,0,1,0}};
LL B[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
LL f[4];
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
sort(a+1,a+1+n,cmp);//此处写成 sort(a+1,a+n)
for(i=1;i<=n;i++)ans=(ans+a[i])%mod;//此处写成ans+=a[i],造成Wrong Answer
f[0]=0,f[1]=ans,f[2]=a[1],f[3]=a[2];
quickPower(A,B);
mulf(B,f);
printf("%lld\n",f[1]);
}
return 0;
}
//P2044 [NOI2012]随机数生成器
//在线测评地址https://www.luogu.org/problemnew/show/P2044
//构造矩阵如下
//[a,1]
//[0,1]*[x[n],c]
//样例没通过,查了半天,发现2阶矩阵,写成了3阶矩阵 for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
// //memcpy(f,G,sizeof(G));//此句竟然没有作用,无奈采用后面一句
//因为上面这个问题,整整查了70分钟,编译器出现的问题。2018-9-24 11:13
//提交60分,测试点2,8,9,10 WA.2018-9-24 11:41
//看了数据,n,m,a,c,X[0]<=10^18,g<=10^8考虑,一不小心,long long 就要溢出,如何解决。
//以下为60分代码。
//考虑 快速乘,详见https://blog.csdn.net/anxdada/article/details/76855632
//20*14=20*2^3+20*2^2+20*2^1+20*2^0
//20*14=20*0+40*1+80*1+160*1
//修改,提交AC。以下代码为100分代码。2018-9-24 16:15
#include <stdio.h>
#include <string.h>
#define LL long long
LL m,a,c,X,n,g,C[3][3],G[3];
LL quickMul(LL a,LL b){
LL ans=0;
while(b){
if(b&1)ans=(ans+a)%m;
a=(a+a)%m;
b>>=1;
}
return ans;//漏了该句
}
void mulself(LL A[3][3]){
LL i,j,k;
memset(C,0,sizeof(C));
for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
C[i][j]=(C[i][j]+quickMul(A[i][k],A[k][j]))%m;
memcpy(A,C,sizeof(C));
}
void mul(LL A[3][3],LL B[3][3]){
LL i,j,k;
memset(C,0,sizeof(C));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
C[i][j]=(C[i][j]+quickMul(A[i][k],B[k][j]))%m;
memcpy(B,C,sizeof(C));
}
void mulf(LL f[3],LL B[3][3]){
LL i,j;
memset(G,0,sizeof(G));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
G[i]=(G[i]+quickMul(B[i][j],f[j]))%m;
memcpy(f,G,sizeof(G));
}
void quickPower(LL n,LL A[3][3],LL B[3][3]){
while(n){
if(n&1)mul(A,B);
mulself(A);
n>>=1;
}
}
int main(){
LL A[3][3]={{0,0,0},{0,1,1},{0,0,1}};
LL B[3][3]={{0,0,0},{0,1,0},{0,0,1}};
LL f[3];
scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&X,&n,&g);
A[1][1]=a,f[0]=0,f[1]=X,f[2]=c;
quickPower(n,A,B);
mulf(f,B);
printf("%lld\n",f[1]%g);
return 0;
}
//P2044 [NOI2012]随机数生成器
//在线测评地址https://www.luogu.org/problemnew/show/P2044
//构造矩阵如下
//[a,1]
//[0,1]*[x[n],c]
//样例没通过,查了半天,发现2阶矩阵,写成了3阶矩阵 for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
// //memcpy(f,G,sizeof(G));//此句竟然没有作用,无奈采用后面一句
//因为上面这个问题,整整查了70分钟,编译器出现的问题。2018-9-24 11:13
//提交60分,测试点2,8,9,10 WA.2018-9-24 11:41
//看了数据,n,m,a,c,X[0]<=10^18,g<=10^8考虑,一不小心,long long 就要溢出,如何解决。
//以下为60分代码。
#include <stdio.h>
#include <string.h>
#define LL long long
LL m,a,c,X,n,g,C[3][3],G[3];
void mulself(LL A[3][3]){
LL i,j,k;
memset(C,0,sizeof(C));
for(i=1;i<=2;i++)//此处写成 for(i=1;i<=3;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
C[i][j]=(C[i][j]+A[i][k]%m*(A[k][j]%m))%m;
memcpy(A,C,sizeof(C));
}
void mul(LL A[3][3],LL B[3][3]){
LL i,j,k;
memset(C,0,sizeof(C));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
C[i][j]=(C[i][j]+A[i][k]%m*(B[k][j])%m)%m;
memcpy(B,C,sizeof(C));
}
void mulf(LL f[3],LL B[3][3]){
LL i,j;
memset(G,0,sizeof(G));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
G[i]=(G[i]+B[i][j]%m*(f[j]%m))%m;
memcpy(f,G,sizeof(G));
}
void quickPower(LL n,LL A[3][3],LL B[3][3]){
while(n){
if(n&1)mul(A,B);
mulself(A);
n>>=1;
}
}
int main(){
LL A[3][3]={{0,0,0},{0,1,1},{0,0,1}};
LL B[3][3]={{0,0,0},{0,1,0},{0,0,1}};
LL f[3];
scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&X,&n,&g);
A[1][1]=a,f[0]=0,f[1]=X,f[2]=c;
quickPower(n,A,B);
mulf(f,B);
printf("%lld\n",f[1]%g);
return 0;
}
//快速乘 训练题
//小余学数论
//在线测评地址http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=609
//采用快速乘
//样例通过,提交AC。
//1<=a,b,c<2^64 对2^64有顾虑,难道是64位系统。2018-9-24 16:46
#include <stdio.h>
#define LL long long
LL quickMul(LL a,LL b,LL c){
LL ans=0;
while(b){
if(b&1)ans=(ans+a)%c;
a=(a+a)%c;
b>>=1;
}
return ans;
}
int main(){
LL a,b,c;
while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF){
printf("%lld\n",quickMul(a,b,c));
}
return 0;
}
//Fibonacci Problem Again
//Fibonacci前n项和
//在线测评地址https://vjudge.net/problem/HIT-2060
//s(n)=f(0)+f(1)+...+f(n-1)+f(n)
//s(n)=s(n-1)+f(n)
//f(n)=f(n-1)+f(n-2)
//[1 1 0]
//[0 1 1]*[s(n-1),f(n),f(n-1)]=[s(n),f(n+1),f(n-1)];
//[0 1 0]
//想了想,为了程序编写更顺畅,决定重设矩阵,采用下面矩阵进行编码
//[0 1 0]
//[1 1 0]*[f(n-1),f(n),s(n-1)]=[f(n),f(n-1)+f(n),s(n-1)+f(n)]=[f(n),f(n+1),s(n)]
//[0 1 1]
//该题在处理a,b时,顺序颠倒了,找到这个问题,花了25分钟。
//样例通过,专门测试了
//0 1
//2
//要提交时,发现Crawling failed 。2018-9-23 14:57
#include <stdio.h>
#include <string.h>
#define LL long long
#define mod 1000000000
LL a,b,c[4][4],g[4];
void mulf(LL a[4][4],LL f[4]){
LL i,j;
memset(g,0,sizeof(g));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
g[i]=(g[i]+a[i][j]*f[j])%mod;
memcpy(f,g,sizeof(g));
}
void mul(LL a[4][4],LL b[4][4]){
LL i,j,k;
memset(c,0,sizeof(c));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
for(k=1;k<=3;k++)
c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
memcpy(b,c,sizeof(c));
}
void mulself(LL a[4][4]){
LL i,j,k;
memset(c,0,sizeof(c));
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
for(k=1;k<=3;k++)
c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
memcpy(a,c,sizeof(c));
}
void quickPower(LL a[4][4],LL b[4][4],LL n){
while(n){
if(n&1)mul(a,b);
mulself(a);
n>>=1;
}
}
int main(){
LL i,j;
while(1){
scanf("%lld%lld",&a,&b);
if(a==b&&a==0)break;
LL A1[4][4]={{0,0,0,0},{0,0,1,0},{0,1,1,0},{0,0,1,1}},f1[4]={0,1,1,1};//f[4] {0,f(1),f(2),s(1)}//此处写成f1[4]={0,1,1,1}//此处写成A1[4][4]={{0,0,1,0},{0,1,1,0},{0,0,1,1},{0,0,0,0}}//此处写成f1[4]={1,1,1,0}//f[4] {0,f(0),f(1),s(0)};
LL B1[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};//此处写成 B1[4][4]={{0,1,0,0},{0,0,1,0},{0,0,0,1},{0,0,0,0}}
if(a==0)f1[3]=0;
else{
quickPower(A1,B1,a-1);//此处写成 quickPower(A1,B1,b-1);
if(a-1>=1)mulf(B1,f1);//此处写成if(b-1>=1)//漏了if(b-1>=1)//漏了此句
}
LL A2[4][4]={{0,0,0,0},{0,0,1,0},{0,1,1,0},{0,0,1,1}},f2[4]={0,1,1,1};
LL B2[4][4]={{0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
quickPower(A2,B2,b);
if(b==0)f2[3]=1;
else
if(b>=1)mulf(B2,f2);//漏了if(a>=1)
printf("%lld\n",(f2[3]-f1[3]+mod)%mod);//此处写成 printf("%lld\n",f2[3]-f1[3]+mod%mod);
}
return 0;
}
//Problem of Precision HDU - 2256
//在线测评地址https://vjudge.net/problem/HDU-2256
//构造矩阵如下:
//[0 1]
//[-1 10]*[f[n-2],f[n-1]]=[f[n-1],f[n]]
//测试同一样例的多组数据时,出现问题,仔细想了想,应该是每处理一组数据时,就应初始化一次,这个没注意到。
//马上修改,样例通过,提交AC,提交前,心怀忐忑,若是不通过,真想不出什么好办法。2018-9-25
#include <stdio.h>
#include <string.h>
#define mod 1024
#define LL long long
void mulf(LL B[3][3],LL f[3]){
LL i,j,k,g[3];
memset(g,0,sizeof(g));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
g[i]=(g[i]+B[i][j]*f[j])%mod;
memcpy(f,g,sizeof(g));
}
void mul(LL A[3][3],LL B[3][3]){
LL i,j,k,c[3][3];
memset(c,0,sizeof(c));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
c[i][j]=(c[i][j]+A[i][k]*B[k][j])%mod;
memcpy(B,c,sizeof(c));
}
void mulself(LL A[3][3]){
LL i,j,k,c[3][3];
memset(c,0,sizeof(c));
for(i=1;i<=2;i++)
for(j=1;j<=2;j++)
for(k=1;k<=2;k++)
c[i][j]=(c[i][j]+A[i][k]*A[k][j])%mod;
memcpy(A,c,sizeof(c));
}
void quickPower(LL A[3][3],LL B[3][3],LL n){
while(n){
if(n&1)mul(A,B);
mulself(A);
n>>=1;
}
}
int main(){
LL T,n;
scanf("%lld",&T);
while(T--){
LL A[3][3]={{0,0,0},{0,0,1},{0,-1,10}},B[3][3]={{0,0,0},{0,1,0},{0,0,1}};//写在while循环之外了
LL f[3]={0,2,10};
scanf("%lld",&n);
quickPower(A,B,n-1);
mulf(B,f);
printf("%lld\n",(f[2]+mod-1)%mod);//+mod原因是 处理 负数
}
return 0;
}