C
有点郁闷,DP我怎么一个小时才写出来。
题意:给一个长度为n的01串,要通一座桥好像,1表示这个桥必须二层,也就是柱子得2根,0表示一层,二层都可以,给了桥面的花费a,柱子的花费b,求最小花费
思路:f[i][j],第i个位置,并且桥目前层数为j+1的最小花费,转移就好了。
#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\n",i,f[i][0],f[i][1]);
}
printf("%lld\n",min(f[n-1][0]+a+b,f[n-1][1]+2*a+b)+b);
}
}
D
好题:注意求分段个数的方法。
题意:给n对数字,求这n对的全排列种,满足第一维元素不递增且第二维元素也不递增的种数,
思路:如果n个数字只有一维,显然答案可以反向来求递增的个数,将n个数字排序,答案就是N!-相同数个数的阶乘乘积,而变为二维的话,我们可以分别求一维和二维递增的答案,而一维二维的答案可能会有重复,重复部分是一维二维都恒增。
#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\n",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);
}