codevs4247 奇特的生物
来源:互联网 发布:阿尔库津战役知乎 编辑:程序博客网 时间:2024/04/20 16:16
题目描述 Description
科学家们最近发现了一种奇怪的生物,它们每天长大一岁,刚出生的宝宝为1岁,且它们的年龄没有上限。已知年龄为1 岁,2岁,3岁,……,k岁的个体具有生育能力,当年龄为i的具有生育能力的个体将长大一岁时会生下ai个1岁的幼崽。假设第一天只有一个年龄为1的幼 崽,现在科学家们想知道第x天年龄为y的个体有多少,但由于该物种增长速度太快,于是他们将这个任务交给了你。由于这个数可能很大,你需要对p取模。
输入描述 Input Description
输入数据第一行给定四个整数k,x,y,p。
第二行包括k个整数,第i个整数代表ai。
输出描述 Output Description
输出数据包含一行,表示第x天年龄为y的个体的数量对p取模后的结果。
样例输入 Sample Input
【样例输入 1】
3 3 1 1007
1 1 1
【样例输入 2】
3 6 2 1007
1 2 1
样例输出 Sample Output
【样例输出1】
2
【样例输出 2】
13
数据范围及提示 Data Size & Hint
【思路】
矩阵乘法。
可以总结出题目所述的转换规则如下:
|F1,F2,F3…Fk| => |a1*F1+a2*F2+…ak*Fk , F1,F2,…Fk-1|
原矩阵A:
|1,0,0,…0|
转换矩阵T:
|a1,1,0,0…|
|a2,0,1,0…|
|.. , ..,..1…|
|ak,0,0 0…|
分类讨论(标号从0开始):
如果y>x 转移不到数目为0
否则
如果y<=k A=A*(T^(x-1))输出A[0][y-1]
否则
A=A*(T^(x-y+k)) 输出A[0][k-1]
(注意到只要是年龄比k大数目就不会发生变化,所以只要把y所对应的计算到k-1即可)
又:其实只要是1岁以后数目都不会发生变化,上述麻烦了。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 typedef long long LL; 6 const int maxn = 30+5; 7 LL k,x,y,m; 8 LL a[maxn]; 9 10 LL multi( LL y , LL cnt ) {11 if ( ! cnt ) return 0 ;12 if ( cnt == 1 ) return y % m ;13 LL rec = multi( y , cnt / 2 ) ;14 rec = ( rec + rec ) % m ;15 if ( cnt % 2 ) rec = ( rec + y ) % m ;16 return rec ;17 }18 struct Matrix{19 int r,c;20 LL N[maxn][maxn];21 void init(int r,int c) {22 this->r=r, this->c=c;23 memset(N,0,sizeof(N));24 }25 Matrix operator*(Matrix& B)const{26 Matrix C;27 C.init(r,B.c);28 for(int i=0;i<C.r;i++)29 for(int j=0;j<C.c;j++)30 {31 for(int k=0;k<c;k++) C.N[i][j] += multi(N[i][k],B.N[k][j]);32 C.N[i][j]%=m;33 }34 return C;35 }36 Matrix pow(LL p) {37 Matrix tmp=*this;38 Matrix ans;39 ans.init(r,r);40 for(int i=0;i<r;i++) ans.N[i][i]=1;41 while(p) {42 if(p&1) ans=ans*tmp;43 tmp=tmp*tmp;44 p>>=1;45 }46 return ans;47 }48 }A,T;49 50 int main() {51 scanf("%lld%lld%lld%lld",&k,&x,&y,&m);52 for(int i=0;i<k;i++) scanf("%lld",&a[i]);53 if(y>x) {54 printf("0");55 return 0;56 }57 A.init(1,k);58 A.N[0][0]=1;59 T.init(k,k);60 for(int i=0;i<k;i++) T.N[i][0]=a[i];61 for(int i=1;i<k;i++) T.N[i-1][i]=1;62 if(y<=k)63 {64 T=T.pow(x-1);65 A=A*T;66 printf("%lld ",A.N[0][y-1]);67 }else {68 x=x-y+k;69 T=T.pow(x-1);70 A=A*T;71 printf("%lld",A.N[0][k-1]);72 }73 return 0;74 }
- codevs4247 奇特的生物
- 拥有奇特捕食方式的生物和它们超乎想象的行为
- 延生物的延生物
- 奇特的物以类聚现象
- 奇特的艺术品
- 【读书笔记】《奇特的一生》
- 奇特的javascript特性
- 奇特的生活秘方
- typedef + 奇特的声明
- 《奇特的一生》
- 读书笔记:《奇特的一生》
- 奇特的js语法
- 一点奇特的经历
- 一个奇特的做法
- 奇特的java类
- 奇特的分数数列
- 05.奇特的一生
- 《奇特的一生》
- BZOJ2875 [Noi2012]随机数生成器
- 洛谷2344 奶牛抗议(DP+BIT+离散化)
- POJ2286 The Rotation Game(IDA*)
- 洛谷2583 地铁间谍 (UVa1025A Spy in the Metro)
- 1016. 部分A+B
- codevs4247 奇特的生物
- 关于正则表达式的解释和使用方法以及案例分析
- codevs3945 完美拓印
- NOI题库1159 Maze
- POJ1182 食物链(并查集)
- NOI题库1814 恼人的青蛙
- NOI题库192 生日蛋糕
- NOI题库1980 陪审团的人选(POJ1015)
- 算法之插入排序