C
有点郁闷,DP我怎么一个小时才写出来。
题意:给一个长度为n的01串,要通一座桥好像,1表示这个桥必须二层,也就是柱子得2根,0表示一层,二层都可以,给了桥面的花费a,柱子的花费b,求最小花费
思路:f[i][j],第i个位置,并且桥目前层数为j+1的最小花费,转移就好了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=2e5+10; const ll INF=1e17; ll f[maxn][2]; char s[maxn]; int main() { int t; scanf("%d",&t); while(t--) { int n,a,b; scanf("%d%d%d",&n,&a,&b); scanf("%s",s+1); f[0][0]=0; f[0][1]=INF; for(int i=1; i<=n-1; i++) { f[i][0]=f[i][1]=INF; if(s[i]=='0') { if(s[i+1]=='0') { if(f[i-1][0]!=INF) f[i][0]=f[i-1][0]+a+b; if(f[i-1][1]!=INF) { f[i][1]=f[i-1][1]+a+2*b; f[i][0]=min(f[i][0],f[i-1][1]+2*a+b); } } else { if(f[i-1][1]!=INF) f[i][1]=f[i-1][1]+a+2*b; if(f[i-1][0]!=INF) f[i][1]=min(f[i][1],f[i-1][0]+2*a+2*b); } } else { if(f[i-1][1]!=INF) f[i][1]=f[i-1][1]+a+2*b; } // printf("%lld %lld %lld ",i,f[i][0],f[i][1]); } printf("%lld ",min(f[n-1][0]+a+b,f[n-1][1]+2*a+b)+b); } }
D
好题:注意求分段个数的方法。
题意:给n对数字,求这n对的全排列种,满足第一维元素不递增且第二维元素也不递增的种数,
思路:如果n个数字只有一维,显然答案可以反向来求递增的个数,将n个数字排序,答案就是N!-相同数个数的阶乘乘积,而变为二维的话,我们可以分别求一维和二维递增的答案,而一维二维的答案可能会有重复,重复部分是一维二维都恒增。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int maxn=3e5+10; const int mod=998244353; #define ll long long struct note { int x,y; } a[maxn]; int cmp1(note a,note b) { return a.x<b.x; } int cmp2(note a,note b) { if(a.y!=b.y) return a.y<b.y; else return a.x<b.x; } ll calc(int x) { ll sum=1; for(int i=1;i<=x;i++) sum=(ll)sum*i%mod; return sum; } int main() { int n; scanf("%d",&n); ll ans=1; for(int i=1; i<=n; i++) { scanf("%d%d",&a[i].x,&a[i].y); ans=(ll)ans*i%mod; } ll temp1=1; sort(a+1,a+1+n,cmp1); for(int i=1; i<=n;) { int j=i; int cnt=0; while(j<=n&&a[i].x==a[j].x) { cnt++; j++; } i=j; temp1=(ll)temp1*calc(cnt)%mod; } sort(a+1,a+1+n,cmp2); ll temp2=1; for(int i=1; i<=n;) { int j=i; int cnt=0; while(j<=n&&a[i].y==a[j].y) { cnt++; j++; } i=j; temp2=(ll)temp2*calc(cnt)%mod; } int flag=1; for(int i=2; i<=n; i++) { if(a[i].x<a[i-1].x||a[i].y<a[i-1].y) { flag=0; break; } } ll temp3=1; if(flag) { for(int i=1;i<=n;) { int j=i; int cnt=0; while(j<=n&&a[i].x==a[j].x&&a[i].y==a[j].y) { cnt++;j++; } i=j; temp3=(ll)temp3*calc(cnt)%mod; } } // printf("%lld %lld %lld %lld ",ans,temp1,temp2,temp3); if(flag) ans=((ans-temp1-temp2+temp3)%mod+mod)%mod; else ans=((ans-temp1-temp2+mod)%mod+mod)%mod; printf("%lld",ans); }