POJ3150:Cellular Automaton

题意看不懂加题目想不通,很菜。

n<=500个数围城环,每次操作对每个数Ai把与i在环上相距不超过d<n/2(包括Ai)的数加起来取模m<=1e6,求K<=1e7次操作后的环。

存在递推关系,构造矩阵吧!比如样例一很丑。

于是矩阵快速幂,n*n*n*logK,很慢。

这个矩阵比较奇怪,每一行都是上一行右移一位,而且每一行和每一列长得一样。也就是说我们只保存第一行就能知道整个矩阵长什么样。

而我们的时间主要浪费在a的相乘上,所以a只维护一行,计算答案时把a还原,更新一行的“a”时亦然,具体见代码。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,mod,d,K;
 9 #define maxn 511
10 int a[maxn],b[maxn];
11 void mul(int *a,int *b,int *ans)
12 {
13     int t[maxn];
14     memset(t,0,sizeof(t));
15     for (int i=1;i<=n;i++)
16         for (int j=1;j<=n;j++)
17             t[i]=(t[i]+1ll*a[j-i+1+(j-i>=0?0:n)]*b[j]%mod)%mod;
18     for (int i=1;i<=n;i++) ans[i]=t[i];
19 }
20 int main()
21 {
22     scanf("%d%d%d%d",&n,&mod,&d,&K);
23     for (int i=1;i<=n;i++) scanf("%d",&b[i]);
24     memset(a,0,sizeof(a));
25     for (int i=1;i<=d+1;i++) a[i]=1;
26     for (int i=n;i>n-d;i--) a[i]=1;
27     while (K)
28     {
29         if (K&1) mul(a,b,b);
30         mul(a,a,a);
31         K>>=1;
32     }
33     for (int i=1;i<=n;i++) printf("%d ",b[i]);
34     return 0;
35 }
View Code

 

posted @ 2017-08-28 19:26  Blue233333  阅读(221)  评论(0编辑  收藏  举报