您的位置:首页 > 其它

poj 2748 Logs Stacking (递推找规律|矩阵乘法)

2016-10-21 09:04 316 查看
Logs Stacking

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 4281 Accepted: 1340
Description

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
[Submit]   [Go Back]   [Status]  
[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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: