Description
衆所周知,HYF有很多小姊妹。 HYF每天放學之後都要跟(不同的)MM約會。HYF這天約會的時候不巧被jzt撞上了……雖然換一個新的MM約會這種事情對於HYF來說如同家常便飯,所謂“好事不出門,壞事傳千里”,jzt迅速將這個消息傳播開來。 每個聽到這個消息的人首先會震驚一段時間(他怎麼又換MM了- -~!),但是這樣的震驚只會持續2個時刻(因爲這對於HYF來說太正常了= =~!)。如果他在第i個時刻聽到這個消息,就會從第(i+2)個時刻開始傳播這個消息,每個時刻把這個消息告訴兩個人,當然他只會告訴不知道這個消息的人。但是當他連續告訴了10個人之後,他就會口乾舌燥,停止傳播。 jzt在第0時刻撞到HYF(當然jzt也有震驚時間),請問第N時刻共有多少人知道了這個消息?
Input Format
一行一個整數N,表示第N時刻。
Output Format
一行一個整數,表示N分鐘後知道這個消息的總人數。
Sample Input
【輸入樣例1】
4
【輸入樣例2】
1
【輸入樣例3】
10
Sample Output
【輸出樣例1】
11
【輸出樣例2】
1
【輸出樣例3】
651
Hint
【樣例1解釋】
時刻0:一開始只有jzt知道
時刻2:jzt開始傳播,時刻2傳播給A和B,時刻3傳播給C和D,時刻4傳播給E和F;
時刻4:A和B在4開始傳播,時刻4傳播給2×2=4個人,傳播給H、I、J、K;
最後知道消息的共有:jzt,A,B,C,D,E,F,H,I,J,K,共11個人。
【數據規模】
20%的數據,N<=20
60%的數據,N<=1000
100%的數據,N<=10000
【題解】
一題比較簡單的遞推,設f[i]記錄第i時刻才知道這件事的人f[0]=1,f[i]=f[i-2]+f[i-3]+f[i-4]+f[i-5]+f[i-6];(最後做個累加就行了)
由於f最後算出來結果很大所以用高精度(剛開始怕會爆內存和超時所以就壓4位,事實證明不壓位也是能過的)(旁邊有的大神高精度時數組開大了就超時最後驗證只能開800然而開了7000的我一臉懵逼)
由於數據範圍比較大,最好用一個滾動數組七個一循環(事實證明不滾動也不會炸)
由於是遞推 還可以用矩陣乘法快速冪的算法優化(雖然矩陣算起來會比較慢 但加上快速冪使算法整體降成log n級別的)
矩陣:
a [1,0,0,0,0,0,0,1]
*f [1,0,2,2,2,2,2,0]
[0,0,2,2,2,2,2,0]
[0,0,1,0,0,0,0,0]
[0,0,0,1,0,0,0,0]
[0,0,0,0,1,0,0,0]
[0,0,0,0,0,1,0,0]
[0,0,0,0,0,0,1,0]
[0,0,0,0,0,0,0,1]
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int i,j,k,l,m,n;
struct info
{
int tot,a[7000];
}f[10],sum,ans;
info operator *(info A,int b)
{
info c;int i,j;
// memset(c.a,0,sizeof c.a);
for (i=1,j=A.tot;i<=j;i++) c.a[i]=A.a[i]*b;c.a[j+1]=c.a[j+2]=0;
for (i=1;i<=j;i++) c.a[i+1]+=c.a[i]/10000,c.a[i]%=10000;
for (;c.a[j+1]!=0;j++,c.a[j+1]=c.a[j]/10000,c.a[j]%=10000);c.tot=j;
return c;
}
info operator +(info A,info B)
{
info c;int i,j;
// memset(c.a,0,sizeof c.a);
for (i=1,j=max(A.tot,B.tot);i<=j;i++) c.a[i]=A.a[i]+B.a[i];c.a[j+1]=0;
for (i=1;i<=j;i++) c.a[i+1]+=c.a[i]/10000,c.a[i]%=10000;
for (;c.a[j+1]!=0;j++,c.a[j+1]=c.a[j]/10000,c.a[j]%=10000);c.tot=j;
return c;
}
info operator -(info A,info B)
{
info c;int i,j;
c=A;
for (i=1,j=min(A.tot,B.tot);i<=j;i++) c.a[i]=c.a[i]-B.a[i];
for (i=1,j=max(A.tot,B.tot);i<=j;i++)
if (c.a[i]<0) c.a[i]+=10000,c.a[i+1]-=1;
for (;c.a[j]==0;j--);c.tot=j;
return c;
}
int main()
{
scanf("%d",&n);
m=1;
f[0].tot=1;f[0].a[1]=1;sum.tot=1;sum.a[1]=0;ans.tot=1;ans.a[1]=1;
for (i=1;i<=n;i++)
{
f[m]=sum*2;
ans=ans+f[m];
if (m==0) k=6;else k=m-1;
sum=sum+f[k];
m=m+1;if (m==7) m=0;
sum=sum-f[m];
}
printf("%d",ans.a[ans.tot]);
for (i=ans.tot-1;i;i--) printf("%d",ans.a[i]);
if (ans.a[i]>999) printf("%d",ans.a[i]);
else if (ans.a[i]>99) printf("0%d",ans.a[i]);
else if (ans.a[i]>9) printf("00%d",ans.a[i]);
else printf("000%d",ans.a[i]);
}