题意:有两个串,每个串的内容要么是数字要么是问号,一共多少种方案使得两个串中存在两个位置一个位置比另一个大,一个位置比另一个小。问号可以填0~9.
思路:
容斥原理,看一共有多少状态减去非法状态,一共的状态数等于10的问号次方,非法状态,要么就是全大于等于,要么就是全小于等于,要么就是全等于,假设res1,res2,res3是这三个解,total是一共的方案数,答案是total-res1-res2+res3,为什么要加上res3呢,因为我们一共要减去的是一个相等的方案数,然后res1,res2里面都包含了全部等于的情况,最后再减去res3。
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
const int mod=1e9+7;
typedef long long ll;
string s1,s2;
int main()
{
ll ans=1;
ll r1=1; //完全大于
ll r2=1;
ll r3=1;
int n;
cin>>n;
cin >> s1 >> s2;
for(int i=0;i<s1.size();i++)
if(s1[i]=='?')
ans=(ll)ans*10%mod;
for(int i=0;i<s2.size();i++)
if(s2[i]=='?')
ans=(ll)ans*10%mod;
//cal r1
for(int i=0;i<n;i++)
{
if(s1[i]!='?' && s2[i]!='?')
{
if(s1[i]<s2[i])
{
r1=0;
break;
}
}
else if(s1[i]=='?' && s2[i]=='?')
{
r1=(ll)r1*55%mod;
}
else if(s1[i]!='?')
{
r1=r1*(s1[i]-'0'+1)%mod;
}
else
r1=r1*(10-(s2[i]-'0'))%mod;
}
// cal r2;
for(int i=0;i<n;i++)
{
if(s1[i]!='?' && s2[i]!='?')
{
if(s1[i]>s2[i])
{
r2=0;
break;
}
}
// 00 11 22 29 99
else if(s1[i]=='?' && s2[i]=='?')
{
r2=(ll)r2*55%mod;
}
else if(s1[i]!='?')
{
r2=r2*(10-(s1[i]-'0'))%mod;
}
else
r2=r2*(s2[i]-'0' + 1)%mod;
}
// cal r3;
for(int i=0;i<n;i++)
{
if(s1[i]!='?' && s2[i]!='?')
{
if(s1[i]!=s2[i])
{
r3=0;
break;
}
}
else if(s1[i]==s2[i])
{
r3=r3*10%mod;
}
}
cout << ((ans - r1 - r2 + r3)%mod+mod)%mod <<endl;
return 0;
}
dp代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
const int mod=1e9+7;
typedef long long ll;
string s1,s2;
ll f[N][4];// f[i][0] 考虑前i个只有s[j]==w[j]的情况
// f[i][1] 只有s[j]>w[j]的情况
// f[i][2] 只有s[j]<w[j]
// f[i][3] 合法状态
int main()
{
int n;
cin >> n;
cin >> s1;
cin >> s2;
s1=' '+s1;
s2=' '+s2;
f[0][0]=1;
for(int i=1;i<=n;i++)
{
if(s1[i]=='?'&&s2[i]=='?')
{
for(char j='0';j<='9';j++)
for(char k='0';k<='9';k++)
{
if(j>k)
{
f[i][3]+=f[i-1][3];
f[i][3]+=f[i-1][2];
f[i][1]+=f[i-1][0];
f[i][1]+=f[i-1][1];
}
else if(j==k)
{
f[i][0]+=f[i-1][0];
f[i][1]+=f[i-1][1];
f[i][2]+=f[i-1][2];
f[i][3]+=f[i-1][3];
}
else if(j<k)
{
f[i][3]+=f[i-1][1];
f[i][3]+=f[i-1][3];
f[i][2]+=f[i-1][0];
f[i][2]+=f[i-1][2];
}
}
}
else if(s1[i]=='?')
{
for(char j='0';j<='9';j++)
{
if(j==s2[i])
{
f[i][0]+=f[i-1][0];
f[i][3]+=f[i-1][3];
f[i][2]+=f[i-1][2];
f[i][1]+=f[i-1][1];
}
else if(j>s2[i])
{
f[i][3]+=f[i-1][3];
f[i][3]+=f[i-1][2];
f[i][1]+=f[i-1][0];
f[i][1]+=f[i-1][1];
}
else if(j<s2[i])
{
f[i][3]+=f[i-1][1];
f[i][3]+=f[i-1][3];
f[i][2]+=f[i-1][0];
f[i][2]+=f[i-1][2];
}
}
}
else if(s2[i]=='?')
{
for(char j='0';j<='9';j++)
{
if(j==s1[i])
{
f[i][0]+=f[i-1][0];
f[i][3]+=f[i-1][3];
f[i][2]+=f[i-1][2];
f[i][1]+=f[i-1][1];
}
else if(j<s1[i])
{
f[i][3]+=f[i-1][3];
f[i][3]+=f[i-1][2];
f[i][1]+=f[i-1][0];
f[i][1]+=f[i-1][1];
}
else if(j>s1[i])
{
f[i][3]+=f[i-1][1];
f[i][3]+=f[i-1][3];
f[i][2]+=f[i-1][0];
f[i][2]+=f[i-1][2];
}
}
}
else
{
if(s1[i]==s2[i])
{
f[i][0]+=f[i-1][0];
f[i][1]+=f[i-1][1];
f[i][3]+=f[i-1][3];
f[i][2]+=f[i-1][2];
}
else if(s1[i]>s2[i])
{
f[i][3]+=f[i-1][3];
f[i][3]+=f[i-1][2];
f[i][1]+=f[i-1][1];
f[i][1]+=f[i-1][0];
}
else
{
f[i][3]+=f[i-1][3];
f[i][3]+=f[i-1][1];
f[i][2]+=f[i-1][2];
f[i][2]+=f[i-1][0];
}
}
f[i][0]%=mod;
f[i][1]%=mod;
f[i][2]%=mod;
f[i][3]%=mod;
}
cout<<f[n][3]<<endl;
return 0;
}