UVA 1386 Cellular Automaton

来源:互联网 发布:ios编写软件 编辑:程序博客网 时间:2024/06/10 02:43

题目链接:http://acm.hust.edu.cn/vjudge/problem/38668


题意:有一个长度为n的圈,里面有n个数,每一次圈里的每个数会变成与它的距离不超过d的数之和(包括自己),求k次后这个圈里的n个数各是多少。


思路:k很大,只能矩阵快速幂计算,很容易可以构造出来转移矩阵,a1,a2,a3,...an  n*n的转移矩阵第i列转移ai去下一个状态,那么aij = 1( abs(i-j)<=d )。

但是存不下500*500的矩阵,而且矩阵的每一列都是相对于前一列整体向下移一位,所以我们只需要保存第一列,就可以记录整个矩阵,矩阵乘法相应的也需要做一下调整。


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <iostream>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <sstream>#include <queue>#include <utility>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))#define LL long long#define ULL unsigned long long#define inf 0x7fffffff#define mod 100000007const int maxn = 509;int n,m,d,k;struct node{    LL a[maxn];    void P( int k , int m = 0 )    {        Clean( a , 0 );        a[0] = 1;        rep(j,1,m)        {            a[j] = a[ k - j ] = 1;        }    }};node multi( node &x , node &y , int z ){    node ans;    rep(i,0,z-1)    {        ans.a[i] = 0;        rep(j,0,z-1)            ans.a[i] = ( ans.a[i] + x.a[(j-i+n)%n] * y.a[j] ) % m;    }    return ans;}int main(){    while( scanf("%d%d%d%d",&n,&m,&d,&k) == 4 )    {        LL x[maxn];        rep(i,0,n-1)        {            scanf("%lld",&x[i]);            x[i] %= m;        }        node ans,temp;        ans.P( n );        temp.P( n , d );        while( k )        {            if ( k & 1 ) ans = multi( temp , ans , n );            temp = multi( temp , temp , n );            k >>= 1;        }        rep(i,0,n-1)        {            LL S = 0;            rep(j,0,n-1)                S = ( S + x[j] * ans.a[(j-i+n)%n] ) % m;            printf("%lld%c",S,( i == n-1 )?'\n':' ');        }    }    return 0;}


0 0
原创粉丝点击