ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

codeforces好题

2022-01-25 10:34:03  阅读:174  来源: 互联网

标签:le int sum 个数 codeforces long 好题 include


CF1515E Phoenix and Computers

这是一道很好的 \(\mathrm{dp}\) 题。

首先我们将电脑打开方式分为两种,一种为手动,一种为自动。

那么我们先来考虑 \(n\) 台电脑全部为手动的情况。

如果先打开 \(1\) 号,那么剩余 \(n-1\) 个数中 \([2,n]\) 的顺序一定是 \(2,3,\dots,n\),共 \(1\) 种。

如果先打开 \(2\) 号,那么剩余 \(n-1\) 个数中 \([3,n]\) 的顺序一定是 \(3,4,\dots,n\),所以这 \(n-2\) 个数可以在 \(n-1\) 个空中随便选 \(n-2\) 个位置,然后在把 \(1\) 填入剩余的空中,共有 \(\binom{n-1}{n-2}\) 种。

如果先打开 \(3\) 号,那么剩余 \(n-1\) 个数中 \([4,n]\) 的顺序一定是 \(4,5,\dots,n\),所以这 \(n-3\) 个数可以在 \(n-1\) 个空中随便选 \(n-3\) 个位置,然后在把 \(2,1\) 按序填入剩余的空中,共有 \(\binom{n-1}{n-3}\) 种。

所以对于一般情况,如果先打开 \(k(1\le k\le n)\) 号,那么剩余 \(n-1\) 个数中 \([k+1,n]\) 的顺序一定是 \(k+1,k+2,\dots,n\),所以这 \(n-k\) 个数可以在 \(n-1\) 个空中随便选 \(n-k\) 个位置,然后在把 \(k,k-1,\dots,1\) 按序填入剩余的空中,共有 \(\binom{n-1}{n-k}\) 种。

所以综上所述,\(n\) 台电脑全部为手动的情况共有 \(\sum_{i=1}^{n}\binom{n-1}{n-k}=2^{n-1}\)。

接下来我们考虑最后电脑开启的状态。

很明显最终电脑的状态是一段手动,一个自动,再来一段手动,如此交替。

设 \(f_{i,j}\) 表示前 \(i\) 台电脑,手动 \(j\) 台,第 \(i\) 台手动,且第 \(i+1\) 台为自动的方案数。

那么转移时就从一段手动转移到下一段手动,即 \(f_{i,j}\to f_{i+k+1,j+k}\)。

我们先来考虑这 \(k\) 台手动内部的顺序,我们已经证明,为 \(2^{k-1}\) 种。

再来考虑原来的 \(j\) 台手动和这 \(k\) 台的手动,可以随意穿插,共有 \(\binom{j+k}{k}\) 种。

以及原有的 \(f_{i,j}\) 种,我们可以得出转移方程 \(f_{i+k+1,j+k}=\sum_{k=1}^{n-i-1}f_{i,j}\times2^{k-1}\times\binom{j+k}{k}\)。

初始化 \(f_{i,i}=2^{i-1}\)。

答案为 \(\sum_{i=1}^nf_{n,i}\)。

时间复杂度:\(O(n^3)\)。

#include<iostream>
using namespace std;
int n,mod;
long long C[405][405],pow2[405],f[405][405],ans;
int main()
{
    cin>>n>>mod;
    C[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    pow2[0]=1;
    for(int i=1;i<=n;i++) pow2[i]=pow2[i-1]*2%mod;
    for(int i=1;i<=n;i++)
    {
        f[i][i]=pow2[i-1];
        for(int j=1;j<=i;j++)
        {
            for(int k=1;k<=n-i-1;k++) f[i+k+1][j+k]=(f[i+k+1][j+k]+f[i][j]*pow2[k-1]%mod*C[j+k][k]%mod)%mod;
        }
    }
    for(int i=1;i<=n;i++) ans=(ans+f[n][i])%mod;
    cout<<ans<<endl;
    return 0;
}

CF1528B Kavi on Pairing Duty

这是一道很好的 \(\mathrm{dp}\) 题。

引理:设 \(1\) 与 \(x\) 配对,则对于每一个 \(p(x<p\le2n)\),设它与 \(q\) 配对,则 \([p,q]\)(或 \([q,p]\))的长度与 \([1,x]\) 的长度相同。

设 \(f_i\) 表示 \(i\) 时的种数。

对 \(x\) 进行分类讨论。

当 \(n+1\le x\le2n\) 时,根据引理可得 \(1\) 与 \(x\) 配对,\(2\) 与 \(x+1\) 配对,\(3\) 与 \(x+2\) 配对,直至 \(2n-x+1\)与\(2n\) 配对。因为 \(n+1\le x\le2n\),所以 \(1\le2n-x+1\le x\),可以想象到连完之后中间会空下连续的一段,共 \(2x-2n-2\) 个点,个数为 \(f_{x-n-1}\)。所以当 \(n+1\le x\le2n\) 时,个数共有 \(\sum_{i=0}^{n-1}f_i\) 种。

当 \(2\le x\le n\) 时,易得 \(x-1\) 为 \(n\) 的约数且不等于 \(n\),设 \(D(n)\) 表示 \(n\) 除自己外的约数个数,则当 \(2\le x\le n\) 时,个数共有 \(D(n)\) 种。

综上,\(f_n=\sum_{i=0}^{n-1}f_i+D(n)\)。

初始化 \(f_0=1\)。

时间复杂度:\(O(n\log n)\)。

#include<iostream>
using namespace std;
long long mod=998244353;
long long n;
long long dp[1000005];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=2;i*j<=n;j++) dp[i*j]++;
    }
    dp[0]=1;
    long long sum=1;
    for(int i=1;i<=n;i++)
    {
        dp[i]=(dp[i]+sum)%mod;
        sum=(sum+dp[i])%mod;
    }
    cout<<dp[n]<<endl;
    return 0;
}

CF1510D Digits

这是一道很好的 \(\mathrm{dp}\) 题。

状态很容易想出,设 \(f_{i,j}\) 表示前 \(i\) 位乘积 \(\%10\) 后为 \(j\),且乘积最大的值。

但是转移时会发现乘积太大,无法直接转移。

因此我们可以运用对数化乘为加,即 \(x\times y=2^{\log_2x}\times2^{\log_2y}=2^{\log_2x+\log_2y}\)。

所以我们只需记录乘积的 \(\log\) 值即可。

转移方程:\(f_{i,k}=max(f_{i-1,k},f_{i-1,j}+\log_2a_i)\)。

至于方案,我们在更新答案的同时用一个 \(pre\) 数组来记录,即 \(pre_{i,k}=j\)。

初始化 \(f_{0,i}=-\inf\),\(f_{0,1}=0\)。

时间复杂度:\(O(10n)\)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,k,cnt;
long long a[100005],pre[100005][15],ans[100005];
double f[100005][15];
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    memset(pre,-1,sizeof(pre));
    for(int i=0;i<=9;i++) f[0][i]=-1e9;
    f[0][1]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=9;j++) f[i][j]=f[i-1][j];
        for(int j=0;j<=9;j++)
        {
            int k=j*a[i]%10;
            if(a[i]==1||f[i][k]<f[i-1][j]+(double)log2(a[i]))
            {
                f[i][k]=f[i-1][j]+(double)log2(a[i]);
                pre[i][k]=j;
            }
        }
    }
    if(f[n][k]<0) cout<<-1<<endl;
    else
    {
        for(int i=n;i>=1;i--)
        {
            if(pre[i][k]!=-1)
            {
                ans[++cnt]=a[i];
                k=pre[i][k];
            }
        }
        if(cnt==0) cout<<-1<<endl;
        else
        {
            cout<<cnt<<endl;
            for(int i=1;i<=cnt;i++) cout<<ans[i]<<" ";
            cout<<endl;
        }
    }
    return 0;
}

CF1027E Inverse Coloring

这是一道很好的 \(\mathrm{dp}\) 题。

引理:当一个正方形的第一行与第一列确定之后,这个正方形的漂亮着色就已经确定了。

证明:易得

因此问题就转变为了要求行与列的最大连续同色长度的乘积 \(<k\)。

行与列相同,所以可以只算一边。

设 \(f_{i,j}\) 表示在前 \(i\) 个中,最大连续黑色长度 \(\le j\) 的个数。

不难得出转移方程:\(f_{i,j}=\sum_{k=i-j}^{i-1}f_{k,min(j,k)}\)。

初始化:\(f_{i,i}=1\)

再利用差分,设 \(sum_i\) 表示长度为 \(n\),且最大连续黑色长度 \(=i\) 的个数。

则 \(ans=\sum_{i=1}^n\sum_{j=1}^nsum_i\times sum_j\ [i\times j<k]\)。

最后因为有黑白两色,不要忘了 \(ans\times 2\)。

时间复杂度:\(O(n^3)\)。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m;
const int mod=998244353;
long long f[505][505],sum[505],ans;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) f[i][i]=1;
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            for(int k=i-j;k<=i-1;k++) f[i][j]=(f[i][j]+f[k][min(j,k)])%mod;
        }
    }
    for(int i=1;i<=n;i++) sum[i]=(f[n][i]-f[n][i-1]+mod)%mod;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i*j<m) ans=(ans+sum[i]*sum[j]%mod)%mod;
        }
    }
    cout<<ans*2%mod<<endl;
    return 0;
}

标签:le,int,sum,个数,codeforces,long,好题,include
来源: https://www.cnblogs.com/SpadeA261/p/codeforces.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有