牛客周赛 Round 11【题解完成】

80 阅读2分钟
题目难度知识点
A 小美的外卖订单编号签到
B 小美的数组操作2签到
C 小美的01串翻转枚举+前缀和
D 小美的元素删除★★计数类DP

这个有好多和之前的一套题重了。

小美的外卖订单编号

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
int main(void)
{
    int t; cin>>t;
    while(t--)
    {
        int m,x; cin>>m>>x;
        cout<<(x-1)%m+1<<'\n';
    }
    return 0;
}

小美的数组操作2

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
typedef long long int LL;
LL a[N],b[N],n,t,k;
int main(void)
{
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=k;i++)
        {
            int x,y; cin>>x>>y;
            a[x]+=1,a[y]-=1;
        }
        for(int i=1;i<=n;i++) b[i]=a[i];
        sort(b+1,b+n+1);
        int flag=1;
        for(int i=1;i<=n;i++) if(a[i]!=b[i]) flag=0;
        if(flag) puts("Yes");
        else puts("No");
    }
    return 0;
}

小美的01串翻转

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
string a,b,c;
LL cnt1[N],cnt2[N];
int main(void)
{
    cin>>a;
    int n=a.size();
    while(b.size()<a.size()) b+="01";
    while(c.size()<a.size()) c+="10";
    a="."+a,b="."+b,c="."+c;
    for(int i=1;i<=a.size();i++)
    {
        cnt1[i]=cnt1[i-1],cnt2[i]=cnt2[i-1];
        if(b[i]!=a[i]) cnt1[i]++;
        if(c[i]!=a[i]) cnt2[i]++;
    }
    LL ans=0;
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int l=j,r=j+i-1;
            if(r>n) break;
            ans+=min(cnt1[r]-cnt1[l-1],cnt2[r]-cnt2[l-1]);
        }
    }
    cout<<ans;
    return 0;
}

小美的元素删除

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e3*2+10;
const int mod=1e9+7;
typedef long long int LL;
LL dp[N][35],a[N],n,k;//dp[i][j]表示以i结尾的,包括i的,子序列长度为j的方案数。
vector<int>ve[N];
int main(void)
{
    cin>>n>>k;
    for(int i=0;i<n;i++) cin>>a[i];
    int m=n-k;
    if(m<=0 || m>=31)//m最大为31 2^31>1e^9
    {
        cout<<0;
        return 0;
    }
    sort(a,a+n);
    for(int i=0;i<n;i++)//建图,说明这些是倍数关系。
        for(int j=i+1;j<n;j++) if(a[j]%a[i]==0) ve[i].push_back(j);
    for(int i=0;i<n;i++)
    {
        dp[i][1]=1;
        for(int j=1;j<m;j++)
        {
            if(dp[i][j]==0) continue;
            for(int z=0;z<ve[i].size();z++)//更传统的不一样的是这里是向后传递的
            {
                int u=ve[i][z];//新加的一个数
                dp[u][j+1]=(dp[u][j+1]+dp[i][j])%mod;
            }
        }
    }
    LL ans=0;
    for(int i=0;i<n;i++) ans=(ans+dp[i][m])%mod;
    cout<<ans;
    return 0;
}