码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #461 (Div. 2) 题解

时间:2018-02-13 18:53:06      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:man   nbsp   printf   memset   []   c++   难点   std   ems   

Codeforces Round #461 (Div. 2)

Codeforces 922C

题意

给定\(n,k \le 10^{18}\),判断是否对于所有的$ i \le k,n mod i$都是不同的

解题思路

首先\(n\ mod\ 1=0\),为了不相同\(n\ mod\ 2=1\)\(n\ mod\ 3=2\)……

\(n\ mod\ i=i-1\)\(n+1\ mod\ i=0\)

直接暴力判断对所有的\(i\)是否成立即可,由于阶乘的增长速度很快,检查的次数几乎是常数

AC代码

#include <bits/stdc++.h>
using namespace std;
long long n,k;
bool solve()
{
    for (long long i=1;i<=k;i++)
        if((n+1)%i)
            return false;
    return true;
}
int main(int argc, char const *argv[])
{
    scanf("%I64d%I64d",&n,&k);
    if(solve())
        puts("Yes");
    else
        puts("No");
    return 0;
}

Codeforces 922D

题意

给定若干由\(s\)\(h\)组成的字符串,输出将这些字符串拼接后这样的对的数量的最大值\(i<j,s_i=‘s‘,s_j=‘h‘\)

解题思路

对于两个字符串\(A,B\),相应\(s,h\)的数量分别为\(s_{str},h_{str}\) ,设不算这两个串互相产生的对对答案的贡献的其他贡献为\(W\),则当前对的数量为\(W+s_Ah_B\),交换后为\(W+s_Bh_A\)

因此按照\(s_{str}/h_{str}\)排序后即是最佳拼接方案,随后计算对的数量即可

AC代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=100007;
struct node
{
    string str;
    long long s,h;
}noise[maxn];
int order[maxn];
bool cmp(int l,int r)
{
    return noise[l].s*noise[r].h>noise[l].h*noise[r].s;
}
int main(int argc, char const *argv[])
{
    int n;
    scanf("%d",&n);
    for (int i=0;i<n;i++)   order[i]=i;
    for (int i=0;i<n;i++)
    {
        cin>>noise[i].str;
        long long s=0,h=0;
        for (int j=0;j<noise[i].str.size();j++)
        {
            if(noise[i].str[j]==‘s‘)    s++;
            else if(noise[i].str[j]==‘h‘)   h++;
        }
        noise[i].s=s;
        noise[i].h=h;
    }
    sort(order,order+n,cmp);
    long long ans=0,bs=0;
    for (int i=0;i<n;i++)
        for (int j=0;j<noise[order[i]].str.size();j++)
        {
            if(noise[order[i]].str[j]==‘h‘) ans+=bs;
            else if(noise[order[i]].str[j]==‘s‘)    bs++;
        }
    printf("%I64d\n",ans);
    return 0;
}

Codeforces 922E

题意

我觉得是本题难点之一,不想写了

思路

即状态dp[i][k]为经过了\(i\)个树召唤了\(k\)个鸟剩余mana的最大值,状态转移方程为:

\[dp[i][j]=max(dp[i][j],min(dp[i-1][j-k]+X,W+(j-k)\times B)-cost_i\times k)\]

AC代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=1007;
long long n,w,b,x;
long long c[maxn],cost[maxn];
long long dp[maxn][10*maxn];
int main(int argc, char const *argv[])
{
    scanf("%I64d%I64d%I64d%I64d",&n,&w,&b,&x);
    for (int i=1;i<=n;i++)  scanf("%I64d",&c[i]);
    for (int i=1;i<=n;i++)  scanf("%I64d",&cost[i]);
    memset(dp,-1,sizeof(dp));
    dp[0][0]=w;
    for (int i=0;i<=n-1;i++)
    {
        int j=0;
        while(dp[i][j]!=-1)
        {
            if(i>0)
                dp[i+1][j]=min(max(dp[i+1][j],dp[i][j]+x),w+j*b);
            else
                dp[i+1][j]=min(max(dp[i+1][j],dp[i][j]),w+j*b);
            for (int k=1;k<=c[i+1];k++)
            {
                long long nxt=min(dp[i][j]+(i>0?x:0),w+j*b)-cost[i+1]*k;
                if(nxt>=0)  dp[i+1][j+k]=max(dp[i+1][j+k],nxt);
            }
            j++;
        }
    }
    for (int i=1;i<=10001;i++)
        if(dp[n][i]<0)
        {
            printf("%d\n",i-1);
            return 0;
        }
    return 0;
}

Codeforces Round #461 (Div. 2) 题解

标签:man   nbsp   printf   memset   []   c++   难点   std   ems   

原文地址:https://www.cnblogs.com/falseangel/p/8447024.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!