JZOJ1732. 消息传播
2016-07-15 19:24
274 查看
题目
Description众所周知,HYF有很多小姊妹。
HYF每天放学之后都要跟(不同的)MM约会。HYF这天约会的时候不巧被jzt撞上了……虽然换一个新的MM约会这种事情对于HYF来说如同家常便饭,所谓“好事不出门,坏事传千里”,jzt迅速将这个消息传播开来。
每个听到这个消息的人首先会震惊一段时间(他怎么又换MM了- -~!),但是这样的震惊只会持续2个时刻(因为这对于HYF来说太正常了= =~!)。如果他在第i个时刻听到这个消息,就会从第(i+2)个时刻开始传播这个消息,每个时刻把这个消息告诉两个人,当然他只会告诉不知道这个消息的人。但是当他连续告诉了10个人之后,他就会口干舌燥,停止传播。
jzt在第0时刻撞到HYF(当然jzt也有震惊时间),请问第N时刻共有多少人知道了这个消息?
Input
一行一个整数N,表示第N时刻。
Output
一行一个整数,表示N分钟后知道这个消息的总人数。
Sample Input
【输入样例1】
4
【输出样例1】
11
【样例解释】
时刻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个人。
【输入样例2】
1
【输出样例2】
1
【输入样例3】
10
【输出样例3】
651
Sample Output
Hint
【数据规模】
20%的数据,N<=20
60%的数据,N<=1000
100%的数据,N<=10000
分析
每个人最多告诉5个人,所以也就是说,每个人能传播消息的时间就是5个时刻,加上惊讶的时间,每个人的影响时间就是7个时刻。再考虑一下每个时刻可以得到消息的人有多少个,就可以了。
题解
很显然,这个时刻知道消息的总人数就是上一个时刻知道消息的总人数加上这个时刻获得消息的总人数。这个时刻获得消息的人数就等于这个时刻可以传播消息的人数×2。
那这个时刻可以传播消息的人数怎么求?
这个可以传播消息的人得到消息的时间一定是≥2的,
而且得到消息的时间一定是≤7。
这样,我们就可以找到一个递推式。
设fi 表示第i个时刻,知道消息的总人数。
fi=fi−1+(fi−2−fi−7)×2
因为最后答案可能很大,所以要用高精度。
但要注意空间,高精度应尝试压位。
code(c++)
#include <cstdio> #include <algorithm> #include <cstring> #include <string.h> #include <cmath> #include <stdlib.h> #include <math.h> #define ll long long #define mo 10000 using namespace std; typedef int arr [1000]; arr f[10003],t,tt,ans; int n; void add(arr a,arr b) { memset(t,0,sizeof(t)); int m=max(a[0],b[0]); for(int i=1;i<=m;i++) { t[i]+=a[i]+b[i]; t[i+1]+=t[i]/mo; t[i]=t[i]%mo; } if(t[m+1]>0)t[0]=m+1;else t[0]=m; } void dd(arr a,arr b) { memset(tt,0,sizeof(tt)); for(int i=1;i<=a[0];i++) { tt[i]+=a[i]-b[i]; while(tt[i]<0) { tt[i]+=mo; tt[i+1]--; } } tt[0]=a[0]; while(!tt[tt[0]])tt[0]--; } int main() { scanf("%d",&n); f[0][0]=1; f[0][1]=1; f[1][0]=1; f[1][1]=1; for(int i=2;i<=n;i++) { if(i>6) { dd(f[i-2],f[i-7]); add(tt,tt); memcpy(f[i],t,sizeof(f[i])); add(f[i],f[i-1]); memcpy(f[i],t,sizeof(f[i])); } else { add(f[i-2],f[i-2]); memcpy(f[i],t,sizeof(f[i])); add(f[i],f[i-1]); memcpy(f[i],t,sizeof(f[i])); } } memcpy(ans,f ,sizeof(ans)); printf("%d",ans[ans[0]]); for(int i=ans[0]-1;i;i--) { if(ans[i]<1000)printf("0"); if(ans[i]<100)printf("0"); if(ans[i]<10)printf("0"); printf("%d",ans[i]); if(ans[i]<0)printf("*"); } }
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- UVa 10394-Twin Primes
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games