トピック:http://poj.org/problem?id=3150
セルオートマトンバイナリ行列乗算+
セルオートマトン
時間制限:12000MSメモリ制限:65536kも
合計提出:3544受理:1428
ケース制限時間:2000ミリ秒
説明
セルラオートマトンは、隣接セルの状態に基づいて、セルの新しい状態を記述する一連のルールに従った離散時間ステップの数を介して進化所定形状のグリッド上のセルの集合です。セルオートマトンの順序は、それが含まれているセルの数です。次数nのオートマトンの細胞は、1からnまで番号が付けられています。
セルの順序は、それが含まれていてもよい、異なる値の数です。1 - 通常、次数mのセルの値は、0からMまでの整数数字であると考えられます。
セルオートマトンの最も基本的な特性の1つは、それが計算されているグリッドのタイプです。次数mの細胞を用いたn次の円形セルオートマトン - この問題では、セルオートマトンの特別な種類を調べます。我々は、N、M-オートマトンとしてセルラオートマトンのような種類を表します。
iとNでJ、M-オートマトンは分として定義されるセル間の距離(| I - J |、N - | I - J |)。細胞のD環境はDより大きくない距離での細胞の集合です。
各D-段階ではすべてのセルの値は、同時に新しい値に置き換えられます。D-ステップ後のセルIの新しい値は、iがmを法セルのd的環境に属するセルの値の和として計算されます。
次の絵は、5,3-オートマトンの1ステップを示します。
問題は、K、D-ステップの後、N、M-オートマトンの状態を計算することです。
入力
(1 000 000≤500≤1≤nは、1≤M、0≤D <n/2、10 000 000≤1≤k)は、入力ファイルの最初の行4つの整数N、M、D、及びKが含ま。1 - - オートマトンの細胞の初期値は2行目は、N個の整数の0からMまでの番号が含まれています。
出力
出力のK d-工程後にN、M-オートマトンのセルの値。
サンプル入力
サンプル入力#1
5 3 1 1
1 2 2 1 2
サンプル入力#2
5 3 1 10
1 2 2 1 2
サンプル出力
サンプル出力#1
2 2 2 2 1
サンプル出力#2
2 0 0 2 2
問題の意味:
環の数がn個、それを操作する方法を定義し、距離dはモジュロMの数の合計よりも小さいです。各操作は、すべてのデータを更新します。k回を求めた後、どのような数になるのだろうか?
アイデア:
それはマトリックス構造01、KSM解決、nはあまりにも少ないの最適化を考えるのは簡単です:通常の行列見つける
:
1100001
1110000
0111000を
.. 。。。
次のように最初の行の行を保持する必要が、乗算を計算します
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)];
コード:
#include<iostream>
#include<stdio.h>
using namespace std;
int n,m,d,k;
long long init[505],tmp[505];
void mul(long long a[],long long b[])
{
long long c[505];
for(int i=0;i<n;i++)
c[i]=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)];
for(int i=0;i<n;i++)
b[i]=c[i]%m;
}
int main()
{
int i,j;
scanf("%d%d%d%d",&n,&m,&d,&k);
for(i=0;i<n;++i)scanf("%lld",&init[i]);
for(tmp[0]=i=1;i<=d;++i)tmp[i]=tmp[n-i]=1;
while(k)
{
if(k&1)
mul(tmp,init);
k>>=1;
mul(tmp,tmp);
}
for(i=0;i<n;i++)
printf("%lld ",init[i]);
printf("\n");
}