Educational Codeforces Round 71 (Rated for Div. 2)

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
",i,f[i][0],f[i][1]);
        }
        printf("%lld
",min(f[n-1][0]+a+b,f[n-1][1]+2*a+b)+b);
    }
}
View Code

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
",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);
}
View Code

E

原文地址:https://www.cnblogs.com/dongdong25800/p/11420456.html