AB
簽到
C
大力DP,f[i][j]表示走到當前位置的方案數,但問題是無法考慮沒走過路徑的未填位置。不過很好解決,向右走的時候實際方案=原方案數*3^(走過的列下側的未填位置數),向下走的時候實際方案=原方案數*3^(走過的行右側的未填位置數),這樣可以處理掉所有的未填位置。

#include<bits/stdc++.h> using namespace std; const int N=5005,mod=998244353; int n,m,k,pw[N],a[N][N],f[N][N],s[N][N],t[N][N]; int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=-1; pw[0]=1;for(int i=1;i<=5000;i++)pw[i]=3ll*pw[i-1]%mod; for(int i=1,x,y;i<=k;i++) { char c;scanf("%d%d %c",&x,&y,&c); if(c=='X')a[x][y]=0; else if(c=='R')a[x][y]=1; else a[x][y]=2; } for(int j=1;j<=m;j++) { for(int i=n;i;i--)s[i][j]=s[i+1][j]+(a[i][j]==-1); } for(int i=1;i<=n;i++) { for(int j=m;j;j--)t[i][j]=t[i][j+1]+(a[i][j]==-1); } f[1][1]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(j>1) { if(!a[i][j-1]||a[i][j-1]==1)f[i][j]=(f[i][j]+1ll*f[i][j-1]*pw[s[i+1][j-1]])%mod; else if(a[i][j-1]==-1)f[i][j]=(f[i][j]+2ll*f[i][j-1]*pw[s[i+1][j-1]])%mod; } if(i>1) { if(!a[i-1][j]||a[i-1][j]==2)f[i][j]=(f[i][j]+1ll*f[i-1][j]*pw[t[i-1][j+1]])%mod; else if(a[i-1][j]==-1)f[i][j]=(f[i][j]+2ll*f[i-1][j]*pw[t[i-1][j+1]])%mod; } } if(a[n][m]==-1)f[n][m]=3ll*f[n][m]%mod; printf("%d",f[n][m]); }
D
構造能力堪憂於是成功墊底……
很容易發現答案是2^n-1,但就是不會構造……
發現可以將2^(n-1)個人時的答案進行如下復制,假設一個答案是A,則可以復制成AA,AB,其中B與A完全不同,再加上A…AB…B就可達到目的

#include<bits/stdc++.h> using namespace std; int n; int main() { scanf("%d",&n); printf("%d\n",(1<<n)-1); vector<string>a; for(int i=1;i<=n;i++) { vector<string>vec; string x=""; for(int j=1;j<=(1<<i-1);j++)x+='A'; for(int j=1;j<=(1<<i-1);j++)x+='B'; vec.push_back(x); for(int j=0;j<a.size();j++) { vec.push_back(a[j]+a[j]); string s=a[j]; for(int k=0;k<s.size();k++)s[k]=s[k]=='A'?'B':'A'; vec.push_back(a[j]+s); } a=vec; } for(int i=0;i<a.size();i++)cout<<a[i]<<endl; }
E
考完發現實際上就是DP,f[i][j][k]表示在區間[i,j],取了k個區間外的數的最大值,也是直接DP就行了

#include<bits/stdc++.h> using namespace std; const int N=405; int n,a[N],f[N][N][N]; int dp(int l,int r,int m) { int&ret=f[l][r][m]; if(ret)return ret; int t=0; if(l>0||r<=n) { if(m<n-(r-l-1)) { if(a[l]<a[r])t=max(t,dp(l,r+1,m+1)); else t=max(t,dp(l-1,r,m+1)); } if(m>=1&&l>=1)t=max(t,a[l]+dp(l-1,r,m-1)); if(m>=1&&r<=n)t=max(t,a[r]+dp(l,r+1,m-1)); } ret=t; return ret; } int main() { cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; a[0]=a[n+1]=-1; for(int i=0;i<=n;i++)cout<<dp(i,i+1,1)<<endl; }
小號打的 rank=426 performance=1931 rating+=149