poj 2748 Logs Stacking (递推找规律|矩阵乘法)
2016-10-21 09:04
316 查看
Logs Stacking
Daxinganling produces a lot of timber. Before loading onto trains, the timberjacks will place the logs to some place in the open air first. Looking from the sideway, the figure of a logs stack is as follows: We have known that the number of logs in each layer is fewer than the lower layer for at least one log, and that in each layer the logs are connected in a line. In the figure above, there are 12 logs in the bottom layer of the stack. Now, given the number of logs in the bottom layer, the timberjacks want to know how many possible figures there may be. Input The first line of input contains the number of test cases T (1 <= T <= 1000000). Then T lines follow. Every line only contains a number n (1 <= n <= 2000000000) representing the number of logs in the bottom layer. Output For each test case in the input, you should output the corresponding number of possible figures. Because the number may be very large, just output the number mod 10^5. Sample Input 4 1 2 3 5 Sample Output 1 2 5 34 Source POJ Monthly--2006.01.22,anonymous |
[Discuss]
题解:递推找规律。
f[i]表示底层为i的答案。
f[i]=f[i-1]+f[i-2]*2+f[i-3]*3+...+f[1]*(i-1)+1
可以发现每次是在f[i]的基础上加了sum[i-1]=f[1]+f[2]+...+f[i-1]
这样就可以O(n)递推。
f[i]=f[i-1]+sum[i-1]
sum[i]=sum[i-1]+f[i]
发现可以构造矩阵
{f[i-1],sum[i],f[i]}* { 1 1 0
1 2 1
0 0 0 }
可以矩阵乘法依然不可以,所以只能找规律了。
发现f[i]数组是循环的,循环节是75000
其实f[i]=fib[2*i-1] (fib 斐波那契数列 1,1,2,3,5,8,13 ) 找fib的循环节
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 1000003
#define p 100000
#define M 75000
using namespace std;
int n,m,f[M+3],sum[M+3];
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d",&n);
f[0]=1;
f[1]=1; sum[1]=1;
for (int i=2;i<=75000;i++)
f[i]=(f[i-1]+sum[i-1])%p,sum[i]=(sum[i-1]+f[i])%p;
for (int i=1;i<=n;i++){
int x; scanf("%d",&x);
printf("%d\n",f[x%M]);
}
}
矩阵乘法的代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 1000003
#define p 100000
using namespace std;
int n,m,f
,sum
,num
;
struct data
{
int x,pos,ans;
}a
;
struct vec{
int a[10][10];
}e,t,ans,ans1;
int cmp(data a,data b)
{
return a.x<b.x;
}
vec mul(vec a,vec b)
{
vec c;
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
{
c.a[i][j]=0;
for (int k=1;k<=3;k++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%p)%p;
}
return c;
}
void change(vec &a,vec b)
{
for (int i=1;i<=3;i++)
for (int j=1;j<=3;j++)
a.a[i][j]=b.a[i][j];
}
vec quickpow(vec &ans,vec t,int x)
{
vec base;
change(base,t);
while (x)
{
if (x&1) ans=mul(ans,base);
x>>=1;
base=mul(base,base);
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
/*scanf("%d",&n);
f[1]=1; sum[1]=1;
for (int i=2;i<=200000;i++)
f[i]=(f[i-1]+sum[i-1])%p,sum[i]=(sum[i-1]+f[i])%p;
for (int i=1;i<=n;i++){
int x; scanf("%d",&x);
printf("%d\n",f[x]);
}*/
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].pos=i;
sort(a+1,a+n+1,cmp);
t.a[1][1]=1; t.a[1][2]=1; t.a[1][3]=0;
t.a[2][1]=1; t.a[2][2]=2; t.a[2][3]=1;
t.a[3][1]=0; t.a[3][0]=0; t.a[3][3]=0;
ans.a[1][1]=0; ans.a[1][2]=1; ans.a[1][3]=0;
for (int i=1;i<=3;i++) ans1.a[i][i]=1;
a[0].x=1;
for (int i=1;i<=n;i++)
{
quickpow(ans1,t,a[i].x-a[i-1].x);
num[a[i].pos]=(ans.a[1][1]*ans1.a[1][2]%p+ans.a[1][2]*ans1.a[2][2]%p)%p;
}
for (int i=1;i<=n;i++)
printf("%d\n",num[i]);
}
相关文章推荐
- poj 2440 DNA (dp|递推|找规律|矩阵乘法)
- POJ - 2118 矩阵乘法来解线性递推
- Blocks - POJ 3734 矩阵乘法递推
- Firepersons - POJ 2118 矩阵乘法递推
- POJ-3420 回顾矩阵乘法解递推.再次提醒自己矩阵木有交换率.
- hdu 6198 dfs枚举找规律+矩阵乘法
- POJ 3734 Blocks 线性递推 矩阵快速幂
- poj 3233 矩阵乘法经典题
- POJ-3420 Quad Tiling 状态压缩+矩阵乘法
- POJ 2440 矩阵乘法
- poj3233之经典矩阵乘法
- POJ_3150_矩阵快速幂+循环矩阵的乘法
- poj 3070(矩阵的乘法)
- 递推的矩阵乘法解决练习1
- POJ 3070 Fibonacci数列 矩阵乘法及乘幂求法
- 线性递推关系与矩阵乘法
- POJ 3318 Matrix Multiplication(矩阵乘法)
- POJ——2506(找规律加大数乘法 )
- 矩阵乘法和二分求阶乘 解线性递推问题(大数据的递推)
- POJ 3213 矩阵乘法(优化)