CF296B dp\容斥
傳送門
文章目錄
- 題意:
- 思路:
題意:
n≤1e5n\le1e5n≤1e5
思路:
求方案數基本就是考慮dpdpdp了,看到nnn這么大可以考慮一下分情況討論的dpdpdp狀態。
設f[i][j]f[i][j]f[i][j]表示到了第iii個,狀態為jjj的方案數,考慮如何定義jjj才能使方案不重不漏。
(1)j==0(1)j==0(1)j==0表示前面只有sk=wks_k=w_ksk?=wk?的方案數。
(2)j==1(2)j==1(2)j==1表示前面只有sj<wjs_j<w_jsj?<wj?但是可以出現sk=wks_k=w_ksk?=wk?的方案數。
(3)j==2(3)j==2(3)j==2表示前面只有sj>wjs_j>w_jsj?>wj?但是可以出現sk=wks_k=w_ksk?=wk?的方案數。
(4)j==3(4)j==3(4)j==3表示前面有sj<wj,sj>wjs_j<w_j,s_j>w_jsj?<wj?,sj?>wj?但是可以出現sk=wks_k=w_ksk?=wk?的方案數。
初始狀態f[0][0]=1f[0][0]=1f[0][0]=1,讓后遞推即可,轉移方程:
(1)ai>bi(1)a_i>b_i(1)ai?>bi?時f[i][2]+=f[i?1][2]+f[i?1][0]f[i][2]+=f[i-1][2]+f[i-1][0]f[i][2]+=f[i?1][2]+f[i?1][0]f[i][3]+=f[i?1][3]+f[i?1][1]f[i][3]+=f[i-1][3]+f[i-1][1]f[i][3]+=f[i?1][3]+f[i?1][1]
(2)ai=bi(2)a_i=b_i(2)ai?=bi?時f[i][0]+=f[i?1][0]f[i][0]+=f[i-1][0]f[i][0]+=f[i?1][0]f[i][1]+=f[i?1][1]f[i][1]+=f[i-1][1]f[i][1]+=f[i?1][1]f[i][2]+=f[i?1][2]f[i][2]+=f[i-1][2]f[i][2]+=f[i?1][2]f[i][3]+=f[i?1][3]f[i][3]+=f[i-1][3]f[i][3]+=f[i?1][3]
(3)ai<bi(3)a_i<b_i(3)ai?<bi?時f[i][1]+=f[i?1][1]+f[i?1][0]f[i][1]+=f[i-1][1]+f[i-1][0]f[i][1]+=f[i?1][1]+f[i?1][0]f[i][3]+=f[i?1][3]+f[i?1][2]f[i][3]+=f[i-1][3]+f[i-1][2]f[i][3]+=f[i?1][3]+f[i?1][2]
解釋一下轉移的含義:
(1)(1)(1)出現了ai>bia_i>b_iai?>bi?的情況,我們就可以把ai<bia_i<b_iai?<bi?的情況加到答案中了,讓后再讓ai=bia_i=b_iai?=bi?的情況加到ai>bia_i>b_iai?>bi?的情況中即可。之后這兩個狀態就變為無效狀態了。
(2)(2)(2)出現了ai=bia_i=b_iai?=bi?的情況,那么對所有情況遞推過來即可。
(3)(3)(3)出現了ai<bia_i<b_iai?<bi?,與上面的(1)(1)(1)情況類似,也是去掉了兩個狀態。
對于???我們沒法比較大小,但是我們直接枚舉[0,9][0,9][0,9]轉移就好啦。
當然還可以容斥來做,無非就四種情況:
(1)(1)(1)全部情況ansansans。
(2)(2)(2)全部大于的情況ans1ans1ans1。
(3)(3)(3)全部等于的情況ans2ans2ans2。
(4)(4)(4)全部小于的情況ans3ans3ans3。
答案即為ans?ans1?ans2?ans3ans-ans1-ans2-ans3ans?ans1?ans2?ans3。
也比較容易算,最后給出了代碼。
dpdpdp
// Problem: B. Yaroslav and Two Strings // Contest: Codeforces - Codeforces Round #179 (Div. 2) // URL: https://codeforces.com/problemset/problem/296/B // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid (tr[u].l+tr[u].r>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n; char a[N],b[N]; LL f[N][5]; //0 前面只有s_j=w_j //1 前面只有s_j<w_j //2 前面只有s_j>w_j //3 前面有 s_j<w_j,s_j>w_jvoid cal(int j) {for(int i=0;i<4;i++) f[j][i]%=mod; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);cin>>n>>(a+1)>>(b+1);f[0][0]=1;for(int i=1;i<=n;i++) {if(a[i]!='?'&&b[i]!='?') {if(a[i]>b[i]) {f[i][2]+=f[i-1][2]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][1];}else if(a[i]==b[i]) {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 {f[i][1]+=f[i-1][1]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][2];}cal(i);}else if(a[i]=='?'&&b[i]!='?') {for(int j='0';j<='9';j++) {if(j>b[i]) {f[i][2]+=f[i-1][2]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][1];}else if(j==b[i]) {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 {f[i][1]+=f[i-1][1]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][2];}cal(i);}}else if(a[i]!='?'&&b[i]=='?') {for(int j='0';j<='9';j++) {if(a[i]>j) {f[i][2]+=f[i-1][2]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][1];}else if(a[i]==j) {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 {f[i][1]+=f[i-1][1]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][2];}cal(i);}}else {for(int j='0';j<='9';j++) {for(int k='0';k<='9';k++) {if(j>k) {f[i][2]+=f[i-1][2]+f[i-1][0];f[i][3]+=f[i-1][3]+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 {f[i][1]+=f[i-1][1]+f[i-1][0];f[i][3]+=f[i-1][3]+f[i-1][2];}}cal(i);}}cal(i);}for(int i=1;i<=n;i++) {for(int j=0;j<=3;j++) printf("%d ",f[i][j]);puts("");}printf("%lld\n",f[n][3]%mod);return 0; } /**/容斥
// Problem: B. Yaroslav and Two Strings // Contest: Codeforces - Codeforces Round #179 (Div. 2) // URL: https://codeforces.com/problemset/problem/296/B // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid (tr[u].l+tr[u].r>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n; char a[N],b[N];LL getall() {LL ans=1;for(int i=1;i<=n;i++) {if(a[i]=='?') ans*=10;if(b[i]=='?') ans*=10;ans%=mod;}return ans%mod; }LL get1() {LL ans=1;for(int i=1;i<=n;i++) {if(a[i]=='?'&&b[i]=='?') ans*=55;else if(a[i]=='?') ans*=(b[i]-'0'+1);else if(b[i]=='?') ans*=(10-(a[i]-'0'));else if(a[i]>b[i]) return 0;ans%=mod;}return ans%mod; }LL get2() {LL ans=1;for(int i=1;i<=n;i++) {if(a[i]=='?'&&b[i]=='?') ans*=10;else if(a[i]=='?'||b[i]=='?') continue;else if(a[i]!=b[i]) return 0ll;ans%=mod;}return ans%mod; }LL get3() {LL ans=1;for(int i=1;i<=n;i++) {if(a[i]=='?'&&b[i]=='?') ans*=55;else if(b[i]=='?') ans*=(a[i]-'0'+1);else if(a[i]=='?') ans*=(10-(b[i]-'0'));else if(a[i]<b[i]) return 0;ans%=mod;}return ans%mod; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);/*int cnt=0;for(int i=0;i<=9;i++) for(int j=0;j<=9;j++) if(i>=j) cnt++;cout<<cnt<<endl;*/cin>>n>>(a+1)>>(b+1);LL ans=getall();ans+=get2(); ans%=mod;ans-=get1(); ans+=mod; ans%=mod;ans-=get3(); ans+=mod; ans%=mod;printf("%lld\n",ans%mod);return 0; } /**/總結
以上是生活随笔為你收集整理的CF296B dp\容斥的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1537 弹珠 背包可行性dp
- 下一篇: 祛斑吃什么中药调理好