給個洛谷網址吧qwq傳送門
這題先說80分做法吧(洛谷上70分)
顯然我們可以對於每一個時間構造一個矩陣表示變化情況,然後我們注意到,因爲,所以每63個時間是一個循環,那麼我們構造63個轉移矩陣,然後連乘起來,再快速冪優化,有點類似於沼澤鱷魚那道題
簡單放一下70分代碼
#include <bits/stdc++.h>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=70;
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m,x,p,t;
int to[N][N],tot;
string l[N][N],s;
int sz;
struct matrix{
int a[N][N];
matrix(){memset(a,0,sizeof(a));}
void build(){
Rep(i,1,sz)a[i][i]=1;
}
void print(){
Rep(i,1,sz)
Rep(j,1,sz)printf("%d%c",a[i][j],j==sz?'\n':' ');
}
matrix operator * (const matrix &x)const {
matrix res;
Rep(i,1,sz)
Rep(j,1,sz)
Rep(k,1,sz)
res.a[i][j]=1ll*(res.a[i][j]+1ll*a[i][k]*x.a[k][j]%p)%p;
return res;
}
}A[N],B,ans;
matrix Qpow(matrix base,int ind){
matrix res;
res.build();
while(ind){
if(ind&1)res=res*base;
base=base*base;
ind>>=1;
}
return res;
}
void output(matrix A){
Rep(i,1,n){
int last=-1e9,tim=0;
Rep(j,1,m){
int pos=to[i][j];
if(A.a[1][pos]==last)tim++;
else{
if(tim)printf("%d %d ",tim,last);
last=A.a[1][pos];
tim=1;
}
}
if(tim)printf("%d %d\n",tim,last);
}
}
int main()
{
read(n),read(m),read(x),read(p),read(t);
Rep(i,1,n)
Rep(j,1,m){
int len;
read(len);
cin>>s;
Rep(k,1,63/len)l[i][j]+=s;
}
Rep(i,1,n)
Rep(j,1,m)
to[i][j]=++tot;
sz=n*m+1;
Rep(k,0,62){
Rep(i,1,n)
Rep(j,1,m)
switch(l[i][j][k]){
case 'C':
A[k+1].a[to[i][j]][to[i][j]]=1;
A[k+1].a[sz][to[i][j]]=x;
break;
case 'U':
if(i>1)A[k+1].a[to[i][j]][to[i-1][j]]++;
break;
case 'D':
if(i<n)A[k+1].a[to[i][j]][to[i+1][j]]++;
break;
case 'L':
if(j>1)A[k+1].a[to[i][j]][to[i][j-1]]++;
break;
case 'R':
if(j<m)A[k+1].a[to[i][j]][to[i][j+1]]++;
break;
}
A[k+1].a[sz][sz]=1;
}
ans.a[1][sz]=1;
if(t<=63){
Rep(i,1,t)ans=ans*A[i];
output(ans);
return 0;
}
B.build();
Rep(i,1,63)B=B*A[i];
ans=ans*Qpow(B,t/63);
Rep(i,1,t%63)ans=ans*A[i];
output(ans);
return 0;
}
建議先寫出70分做法,這樣對於思考滿分做法有很大幫助,而且滿分代碼只需要在70分代碼上簡單改動就可以了
接下來我們考慮滿分做法,我們考慮我們最開始設計的那些轉移矩陣,其實非常稀疏,除了1那一行以外每一行就一個數,那麼相應的引申出兩種解決方案,一個是用鏈表來存矩陣,好像大家都是這麼做的,但是我tcl,只能寫更弱的方法
我們發現,一些水珠經過一段時間去了哪裏我們是確定的,所以我們把原來的矩陣轉化成一個線性表,表示重新標號之後編號爲的點最後去了哪裏,那麼顯然在兩個"矩陣"和合併成一個新的"矩陣"的時候,,這個還是挺好理解的吧qwq,那麼接下來考慮產生水的情況,我們用表示"矩陣"在這個時間內點處新產生了多少水,那麼我們考慮"矩陣",合併成之後,點所含的水珠格式,首先應該包含,同時,對於所有的,應該還要包含,因爲他從經過的作用,到達了,那麼我們最後發現這個數組可以融入到中,也必須這樣,因爲當我們後面做快速冪的時候,是一下乘上表示一段的"矩陣",但是只能表示一個時間的情況。
所以如果你剛纔寫的是重載運算符的寫法,你只需要把重載乘號的地方改一下,建立"矩陣"的部分改一下,還有建立單位矩陣的方式改一下就好了
對於新的"矩陣"的"單位矩陣",我們讓就可以了
#include <bits/stdc++.h>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=105;
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m,x,p,t;
int to[N][N],tot;
string l[N][N],s;
int sz;
struct matrix{
int link[N*N],val[N*N];
matrix(){memset(link,0,sizeof(link)),memset(val,0,sizeof(val));}
void build(){
Rep(i,1,sz)link[i]=i;
}
void print(){
Rep(i,1,n)
Rep(j,1,m)
printf("%d%c",val[to[i][j]],j==m?'\n':' ');
}
matrix operator * (const matrix &x)const {
matrix res;
Rep(i,1,sz)
res.link[i]=x.link[link[i]];
Rep(i,1,sz)res.val[x.link[i]]+=val[i],res.val[x.link[i]]%=p;
Rep(i,1,sz)res.val[i]+=x.val[i],res.val[i]%=p;
return res;
}
}A[N],B,ans;
matrix Qpow(matrix base,int ind){
matrix res;
res.build();
while(ind){
if(ind&1)res=res*base;
base=base*base;
ind>>=1;
}
return res;
}
void output(matrix A){
Rep(i,1,n){
int last=-1e9,tim=0;
Rep(j,1,m){
int pos=to[i][j];
if(A.val[pos]==last)tim++;
else{
if(tim)printf("%d %d ",tim,last);
last=A.val[pos];
tim=1;
}
}
if(tim)printf("%d %d\n",tim,last);
}
}
int main()
{
read(n),read(m),read(x),read(p),read(t);
Rep(i,1,n)
Rep(j,1,m){
int len;
read(len);
cin>>s;
Rep(k,1,63/len)l[i][j]+=s;
}
Rep(i,1,n)
Rep(j,1,m)
to[i][j]=++tot;
sz=n*m;
Rep(k,0,62){
Rep(i,1,n)
Rep(j,1,m)
switch(l[i][j][k]){
case 'C':
A[k+1].link[to[i][j]]=to[i][j];
A[k+1].val[to[i][j]]+=x;
break;
case 'U':
if(i>1)A[k+1].link[to[i][j]]=to[i-1][j];
break;
case 'D':
if(i<n)A[k+1].link[to[i][j]]=to[i+1][j];
break;
case 'L':
if(j>1)A[k+1].link[to[i][j]]=to[i][j-1];
break;
case 'R':
if(j<m)A[k+1].link[to[i][j]]=to[i][j+1];
break;
}
}
if(t<=63){
Rep(i,1,t)ans=ans*A[i];
output(ans);
return 0;
}
B.build();
Rep(i,1,63)B=B*A[i];
ans=Qpow(B,t/63);
Rep(i,1,t%63)ans=ans*A[i];
output(ans);
return 0;
}