日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UVA1386 【Cellular Automaton】题解

發(fā)布時間:2025/6/17 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UVA1386 【Cellular Automaton】题解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題面:UVA1386 Cellular Automaton

矩陣乘法+快速冪解法:

這是一個比較裸的有點復雜需要優(yōu)化的矩乘快速冪,所以推薦大家先做一下下列洛谷題目練練手:

(會了,差不多就是多倍經(jīng)驗題了)

注:如果你還不會矩陣乘法,可以移步了解一下P3390的題解

P1939 【模板】矩陣加速(數(shù)列)

P3390 【模板】矩陣快速冪

P1962 斐波那契數(shù)列

P4910 帕秋莉的手環(huán)

P4838 P哥破解密碼

然后講一下本題,讀題我們發(fā)現(xiàn)這個環(huán)上所進行的 k 次操作都是一模一樣的,還是相鄰的數(shù)的和,于是想到用矩陣快速冪來寫。

解題思路:

我們可以根據(jù) d 的值來建出基礎矩陣,舉個例子(樣例):

1 1 0 0 11 1 1 0 00 1 1 1 00 0 1 1 11 0 0 1 1

這是樣例每一次操作所對應的乘法矩陣。我們要求出 k 次操作后的環(huán)上的元素等同于乘以 k 次這個矩陣,而這個過程可以直接用快速冪優(yōu)化成log復雜度。

于是我們便可以光明正大的提交,然后光榮 TLE 了

為什么呢?我們看到數(shù)據(jù)范圍:$ n \leq 500$ !眾所周知:矩陣乘法中矩陣上每一個元素都會被用行乘列的方式更新,所以復雜度為 \(n^3\),在乘上快速冪的一個log n ,不TLE才怪!

優(yōu)化方案:

于是我們嘗試優(yōu)化一下(把那個\(n^3\)降到\(n^2\)):我們再看到上面樣例的矩陣,可以發(fā)現(xiàn)它的下一行等于上一行所有的 1 向右移一位。所以我們進行矩陣乘法時可以不更新矩陣的每一個位置,而是只更新它的第一行(將它壓縮一下)其它幾行可以通過第一行推出來。

例如:

0 2 1 1 2

我們可以通過這一行推出整個矩陣(向右移一位):

0 2 1 1 2 2 0 2 1 1 1 2 0 2 1 1 1 2 0 2 2 1 1 2 0

于是乎,我們寫一個新的”矩陣乘法“代碼如下:

void cheng(ll a[],ll b[]){for(int i=1;i<=n;i++)//預處理 1res[i]=0,s[1][i]=b[i];for(int i=2;i<=n;i++){s[i][1]=s[i-1][n];for(int j=2;j<=n;j++)s[i][j]=s[i-1][j-1];}// 解壓一維矩陣,復雜度不會變回 n^3!for(int i=1;i<=n;i++)for(int k=1;k<=n;k++)res[i]+=(a[k]*s[i][k])%m,res[i]%=m;for(int i=1;i<=n;i++)a[i]=res[i]; }// 本題專用“矩陣乘法” //請不要直接給a數(shù)組賦值,不然后果自負!

然后在用快速冪優(yōu)化一下:

while(k){if(k&1)cheng(ans,base);cheng(base,base);k>>=1;}

完整代碼:

#include<iostream> #include<cstdio> #include<iomanip> #include<algorithm>#define ll long long #define db double #define inf 0x7fffffffusing namespace std;const int l=501; int n,m,d,k; ll s[l][l]; ll ans[l],base[l],res[l]; // ans=(answer),base(基礎矩陣),res=(result) // s數(shù)組是用來解壓矩陣的(將一維矩陣換成二維)inline ll qr(){char ch;while((ch=getchar())<'0'||ch>'9');ll res=ch^48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+(ch^48);return res; }void cheng(ll a[],ll b[]){for(int i=1;i<=n;i++)//預處理 1res[i]=0,s[1][i]=b[i];for(int i=2;i<=n;i++){s[i][1]=s[i-1][n];for(int j=2;j<=n;j++)s[i][j]=s[i-1][j-1];}// 解壓一維矩陣,復雜度不會變回 n^3!for(int i=1;i<=n;i++)for(int k=1;k<=n;k++)res[i]+=(a[k]*s[i][k])%m,res[i]%=m;for(int i=1;i<=n;i++)a[i]=res[i]; }// 本題專用“矩陣乘法” //請不要直接給a數(shù)組賦值,不然后果自負!int main(){while(scanf("%d%d%d%d",&n,&m,&d,&k)!=EOF){for(int i=1;i<=n;i++)//預處理 2ans[i]=qr(),base[i]=0;for(int i=0;i<=d;i++)//單位矩陣base[1+i]=base[(n-i)%n+1]=1;while(k){if(k&1)cheng(ans,base);cheng(base,base);k>>=1;}// 只有四行的快速冪for(int i=1;i<n;++i){printf("%lld ",ans[i]);}printf("%lld\n",ans[n]);}return 0; }//預處理 1:將res數(shù)組歸零,將b數(shù)組賦值給s數(shù)組第一維以便壓縮//預處理 2:給ans數(shù)組賦初值,將單位矩陣清零

注:解壓矩陣會消耗很多時間,也可以不解壓,但乘起來會有些麻煩(蒟蒻手殘,就不壓行了吧)。

轉載于:https://www.cnblogs.com/812-xiao-wen/p/9871484.html

總結

以上是生活随笔為你收集整理的UVA1386 【Cellular Automaton】题解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。