Problem 1013 - 时间工厂
Time Limit: 1000MS Memory Limit: 65536KB Difficulty:
Total Submit: 384 Accepted: 79 Special Judge: No
Total Submit: 384 Accepted: 79 Special Judge: No
Description
zyf总是有很多奇异的想法,他最近常常幻想着以后能开这么一个工厂,可以把前三天里生产出来的东西拿到今天来拼在一起作为今天生产的东西。假如前三天生产出来的产品数分别是x,y,z,那么今天就能生产出x+y+z个。这样一来只要前三天的投入,接下来的工厂每一天都是0成本运作,但产品数却在极速增加,相当暴利。
当然,为了防止地球被破坏,为了维护世界的和平,zyf是不会让工厂每天生产出来的东西超过1000000006个的,如果超过了,就不停减去1000000007,减到不超过为止。
现在zyf想知道如果第一、二、三天分别生产a,b,c个产品的话,第n天会生产出多少产品呢?
Input
输入数据的第一行case数。
接下来每一行都有四个数字a,b,c,n(1<=a,b,c,n<=10^9),意义如上文.
接下来每一行都有四个数字a,b,c,n(1<=a,b,c,n<=10^9),意义如上文.
Output
对于每个case输出一行,第n天生产的产品数。
Sample Input
2
1 2 3 4
1 1 1 5
1 2 3 4
1 1 1 5
Sample Output
6
5
5
Hint
Source
Qinz
矩阵乘法,递推优化.XDOJ上不能用__int64,真蛋疼.
#include<stdio.h>
const __int64 M=1000000007;
int main()
{
int a,b,c,n,i,j,k,T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d%d",&a,&b,&c,&n);
__int64 E[3][3]={{0,0,1},{1,0,1},{0,1,1}};
__int64 A[3][3]={{a,b,c},{0,0,0},{0,0,0}};
__int64 tmp[3][3];
if (n<=3)
{
if (n==1) printf("%d
",a);
else if (n==2) printf("%d
",b);
else if (n==3) printf("%d
",c);
continue;
}
n-=3;
while (n)
{
if (n&1)
{
for (i=0;i<3;i++)
for (j=0;j<3;j++)
tmp[i][j]=A[i][j];
for (i=0;i<3;i++)
for (j=0;j<3;j++)
{
A[i][j]=0;
for (k=0;k<3;k++) A[i][j]+=tmp[i][k]*E[k][j];
A[i][j]%=M;
}
}
n>>=1;
for (i=0;i<3;i++)
for (j=0;j<3;j++)
tmp[i][j]=E[i][j];
for (i=0;i<3;i++)
for (j=0;j<3;j++)
{
E[i][j]=0;
for (k=0;k<3;k++) E[i][j]+=tmp[i][k]*tmp[k][j];
E[i][j]%=M;
}
}
printf("%I64d
",A[0][2]);
}
return 0;
}