8.10 NOI 模擬賽 ldysb dp套dp dp
阿新 • • 發佈:2020-08-12
LINK:ldysb
其實我不會這道題的正解 題解就來了一句dp套dp 只有STD的我 無能為力.
這裡寫主要是因為考試的時候連40分的暴力都打不出來.
先考慮20分的暴力.
可以得知 每次必然是從 3,5,7...這些地方點的.
而且順序滿足 點過後面的前面就點不了了.
所以可以\(f_{i,j}\)表示前i個能否形成字元j.
暴力列舉轉移就是n^2的.
考慮怎麼線性判斷.
從前往後 那麼就有因為不知道後面的給的是0還是1 而無法判斷.
我們考慮設計狀態來解決這個情況.
想解決這個問題 需要暴力列舉下一位是什麼,有\(f_{i,j}\)表示 到了第i個位置下一位是j 那麼前面的能變成什麼.
然後可能變成0/1 再開一維記錄即可.
這樣就把所有的情況給壓縮起來了.
算是一個套路吧 狀態中暴力列舉下一次的狀態來進行dp.
score 40
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<ctime> #include<cctype> #include<queue> #include<deque> #include<stack> #include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<cctype> #include<cstdlib> #include<queue> #include<deque> #include<stack> #include<vector> #include<algorithm> #include<utility> #include<bitset> #include<set> #include<map> #define ll long long #define db double #define INF 1000000000 #define inf 1000000000000000ll #define ldb long double #define pb push_back #define put_(x) printf("%d ",x); #define get(x) x=read() #define gt(x) scanf("%d",&x) #define gi(x) scanf("%lf",&x) #define put(x) printf("%d\n",x) #define putl(x) printf("%lld\n",x) #define rep(p,n,i) for(RE int i=p;i<=n;++i) #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]]) #define fep(n,p,i) for(RE int i=n;i>=p;--i) #define vep(p,n,i) for(RE int i=p;i<n;++i) #define pii pair<int,int> #define mk make_pair #define RE register #define P 13331ll #define gf(x) scanf("%lf",&x) #define pf(x) ((x)*(x)) #define uint unsigned long long #define ui unsigned #define EPS 1e-5 #define sq sqrt #define S second #define F first #define mod 1000000007 #define md 998244353 #define max(x,y) ((x)<(y)?y:x) #define l(i) t[i].l #define r(i) t[i].r #define mx(i) t[i].mx #define w(i) t[i].w #define zz p<<1 #define yy p<<1|1 using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { RE int x=0,f=1;RE char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } inline ll Read() { RE ll x=0,f=1;RE char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } const int MAXN=100010; int T,n; char a[MAXN]; int w[8]; int b[MAXN]; int f[MAXN][2][2]; int main() { freopen("ldysb.in","r",stdin); freopen("ldysb.out","w",stdout); scanf("%d",&T); while(T--) { scanf("%s",a+1); w[0]=a[1]-'0'; w[4]=a[2]-'0'; w[2]=a[3]-'0'; w[6]=a[4]-'0'; w[1]=a[5]-'0'; w[5]=a[6]-'0'; w[3]=a[7]-'0'; w[7]=a[8]-'0'; scanf("%s",a+1); n=strlen(a+1); if(n==1&&a[1]=='1'){puts("1");continue;} if(n<=2){puts("0");continue;} rep(1,n,i) { if(a[i]=='?')return 0; f[i][0][0]=f[i][0][1]=0; f[i][1][0]=f[i][1][1]=0; b[i]=a[i]-'0'; } f[2][0][w[b[1]<<2|b[2]<<1]]=1; f[2][1][w[b[1]<<2|b[2]<<1|1]]=1; for(int i=4;i<=n;i+=2) { //merge int ww; rep(0,1,j) { if(!f[i-2][b[i-1]][j])continue; //j a[i] f[i][0][w[j<<2|b[i]<<1]]=1; f[i][1][w[j<<2|b[i]<<1|1]]=1; } //not merge rep(0,1,j) { // a[i-1] a[i] j ww=w[b[i-1]<<2|b[i]<<1|j]; rep(0,1,k)if(f[i-2][ww][k])f[i][j][k]=1; } } put(f[n-1][b[n]][1]); } return 0; }
統計方案數需要dp套dp 學過但不太會 自閉.
std
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> PII; const int maxn=100010,mod=998244353; #define MP make_pair #define lson o<<1,l,mid #define rson o<<1|1,mid+1,r #define FOR(i,a,b) for(int i=(a);i<=(b);i++) #define ROF(i,a,b) for(int i=(a);i>=(b);i--) #define MEM(x,v) memset(x,v,sizeof(x)) inline int read(){ int x=0,f=0;char ch=getchar(); while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return f?-x:x; } int n,p[maxn],s[maxn],to[16][2][2],f[maxn][16]; char str[maxn]; inline void qmo(int &x){x+=(x>>31?mod:0);} void solve(){ scanf("%s",str); FOR(i,0,7) p[i]=str[i]-'0'; FOR(i,0,16) FOR(s1,0,1) FOR(s2,0,1){ int s=0; FOR(k,0,1){ s|=((i>>(k<<1|s1))&1)<<(p[s2<<1|k]<<1); s|=((i>>(k<<1|s1))&1)<<(p[s2<<1|k|4]<<1|1); s|=((i>>(k<<1|p[s2<<1|s1]))&1)<<(k<<1); s|=((i>>(k<<1|p[s2<<1|s1|4]))&1)<<(k<<1|1); } to[i][s1][s2]=s; } scanf("%s",str+1); n=strlen(str+1); FOR(i,1,n) s[i]=(str[i]=='?'?-1:str[i]-'0'); f[0][9]=1; for(int i=0;i+2<=n;i+=2) FOR(j,0,15){ if (s[i+1]!=1 && s[i+2]!=1) qmo(f[i+2][to[j][0][0]]+=f[i][j]-mod); if (s[i+1]!=0 && s[i+2]!=1) qmo(f[i+2][to[j][1][0]]+=f[i][j]-mod); if (s[i+1]!=1 && s[i+2]!=0) qmo(f[i+2][to[j][0][1]]+=f[i][j]-mod); if (s[i+1]!=0 && s[i+2]!=0) qmo(f[i+2][to[j][1][1]]+=f[i][j]-mod); } int ans=0; FOR(i,0,15){ if (s[n]!=1 && ((i>>2)&1)) qmo(ans+=f[n-1][i]-mod); if (s[n]!=0 && ((i>>3)&1)) qmo(ans+=f[n-1][i]-mod); } printf("%d\n",ans); MEM(f,0); } int main(){ int T=read(); while(T--) solve(); }