Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings(容斥原理)
题目大意
对于两个数字串 S 和 W,如果存在 i 和 j 使得:S(i)>W(i) && S(j)<W(j) 那么说这两个串是不可比较的,现在给了两个长度均为 n(1≤n≤105) 的串 S 和 W,用 '?' 代表未知的字母,问,有多少种可能的情况,使得 S 和 W 不可比较?
做法分析
这是 Div2 为数不多的比较坑的题目,当时比赛的时候貌似的时候才两三百人过
求出所有可能的情况的数量,设为 ans
求出 S 比 W 大的情况,即:S(i)≥W(i) 的情况数量,设为 res1
求出 S 比 W 小的情况,即;S(i)≤W(i) 的情况数量,设为 res2
求出 S 和 W 相等的情况,即:S(i)==W(i) 的情况数量,设为 res3
那么,利用容斥原理:最后的结果应该是 ans-res1-res2+res3
参考代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 typedef long long LL; 8 const int N=100006; 9 const int MOD=1000000007; 10 11 char S[N], W[N]; 12 int n, cnt; 13 14 LL calMax() 15 { 16 LL res=1; 17 for(int i=0; i<n; i++) 18 { 19 if(S[i]!='?' && W[i]!='?') 20 { 21 if(S[i]>=W[i]) res*=1; 22 else res*=0; 23 continue; 24 } 25 if(S[i]!='?') res=(res*(S[i]-'0'+1))%MOD; 26 else if(W[i]!='?') res=(res*('9'-W[i]+1))%MOD; 27 else res=(res*55)%MOD; 28 } 29 return res; 30 } 31 32 LL calMin() 33 { 34 LL res=1; 35 for(int i=0; i<n; i++) 36 { 37 if(S[i]!='?' && W[i]!='?') 38 { 39 if(S[i]<=W[i]) res*=1; 40 else res*=0; 41 continue; 42 } 43 if(S[i]!='?') res=res*('9'-S[i]+1)%MOD; 44 else if(W[i]!='?') res=res*(W[i]-'0'+1)%MOD; 45 else res=res*55%MOD; 46 } 47 return res; 48 } 49 50 LL calEqu() 51 { 52 LL res=1; 53 for(int i=0; i<n; i++) 54 { 55 if(S[i]!='?' || W[i]!='?') 56 { 57 if(S[i]!='?' && W[i]!='?' && S[i]!=W[i]) res=0; 58 continue; 59 } 60 res=res*10%MOD; 61 } 62 return res; 63 } 64 65 int main() 66 { 67 scanf("%d", &n); 68 scanf("%s%s", S, W); 69 cnt=0; 70 for(int i=0; i<n; i++) 71 { 72 if(S[i]=='?') cnt++; 73 if(W[i]=='?') cnt++; 74 } 75 LL ans=1; 76 for(int i=0; i<cnt; i++) ans=(ans*10)%MOD; 77 LL res1=calMax(), res2=calMin(), res3=calEqu(); 78 printf("%I64d\n", (ans-res1-res2+res3+MOD+MOD)%MOD); 79 return 0; 80 }
题目链接 & AC通道
Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings