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
",x)
#define putl(x) printf("%lld
",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
",ans);
MEM(f,0);
}
int main(){
int T=read();
while(T--) solve();
}