Codeforces Round #404 div2 (CodeForces - 785ABCD) 题解

12 篇文章 0 订阅
10 篇文章 0 订阅

Codeforces Round #404 div2 题解

数学专场?
传送门:HustOJ
传送门:官方题解以及官方hint还是很给力的,比如我的D题


CodeForces 785A Anton and Polyhedrons

题意,思路

太水了。。。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=800;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int main()
{
    _;
    int n;
    while(cin>>n)
    {
        LL sum=0;
        for(int i=0;i<n;i++)
        {
            string s;cin>>s;
            if(s[0]=='T') sum+=4;
            else if(s[0]=='C') sum+=6;
            else if(s[0]=='O') sum+=8;
            else if(s[0]=='D') sum+=12;
            else if(s[0]=='I') sum+=20;
        }
        cout<<sum<<endl;
    }
    return 0;
}

CodeForces 785B Anton and Classes

题意

有两种课各n,m节,接下来给你n节课的起止时间,m节课的起止时间。这人要上两种课各一节,问你他在两种课中间休息时间最长能到多长。

思路

不难。四个变量,分别记录第一种课最晚开始与最早结束的时间,第二种课最晚开始和最早结束的时间,比一下,就能确定先上那种课,以及最长休息时间。
注意数据范围,反正我直接LL。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=800;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int main()
{
    _;
    int n;
    while(cin>>n)
    {
        LL m1=0, m2=loo, m3=0, m4=loo;
        for(int i=0;i<n;i++)
        {
            LL a, b;cin>>a>>b;
            m1=max(m1, a);m2=min(m2, b);
        }
        int m;cin>>m;
        for(int i=0;i<m;i++)
        {
            LL a, b;cin>>a>>b;
            m3=max(m3, a);m4=min(m4, b);
        }
        LL t1, t2;
        if(m2<m3) t1=m3-m2;
        else t1=0;
        if(m4<m1) t2=m1-m4;
        else t2=0;
        cout<<max(t1, t2)<<endl;

    }
    return 0;
}

CodeForces 785C Anton and Fairy Tale

题意

一个粮仓,容量n。最开始是满的,以后每天会填进去m的米,如果溢出,那么实际存米量还是n。第i天会有i只麻雀,每只吃1米,共吃i米。问哪天麻雀吃完米后粮仓第一次出现空。至于边界判定的问题,看原题吧。

思路

比较烦人的题。。。官方的hint说手工模拟计算,的确。。

首先,如果n<=m,那么肯定是第n天。

如果n>m,那么第m+1天填过米,粮仓肯定是最后一次满的。之后粮仓不在会满。这样就可以考虑每天麻雀先吃,第二天在填米之后的净减少量。这个值从1开始增大。停止的条件是,某一天的米不够吃了,这样当天吃过米后,粮仓第一次出现空。

设m天后过了k天:
列出方程: nk(k+1)2<m+k

求满足条件的最小正整数k。

关于这个方程,在y轴右侧是单调递增的。求根公式啊,二分啊都行。

代码

求根公式搞完了,注意k要>0

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=800;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int main()
{
    //_;
    LL n;
    while(cin>>n)
    {
        LL m;cin>>m;
        LL res;
        if(n<=m) res=n;
        else
        {
            res=m+1;
            LL k=((-3+sqrt(9+4*(2*n-2*m-2)))/2);
            while(k*k+3*k-(2*n-2*m-2)<0) k++;

            res+=k;
        }
        cout<<res<<endl;
    }
    return 0;
}

CodeForces 785D Anton and School - 2

题意

读原题吧。。题意里面有概念,我很迷。。

大体是,给你一串括号,让你找一个长度为非零偶数子串,满足一半左括号一半右括号。

思路

很好的一道组合数学题。。在永刚大佬的帮助下做出来的。。。还是那句话,官方的hint挺不错的。

官方说先看这种子串:((())))),就是前面全是左括号,后面跟的全是右括号的。这种串的做法其实跟普通串一样。

做法是:先统计每个右括号前面的左括号数,记为l[i],i表示在原string中的位置。在统计每个右括号后面的右括号数r[i]。

比如((())))),l数组:00033333,r数组:00043210。然后我们看第一个),l=3,r=4。右括号以他为首的括号子串个数:

C13+C14C23+C24C33

然后发现,对于一个l值是a,r值是b的右括号,它贡献的结果是:

C0bC1a+C1bC2a+C2bC3a++Ca1bCaa
这里面的含义,手工模拟一下,应该不难理解。

用组合数公式化简。。膜永刚大佬。。:

CbbC1a+Cb1bC2a+Cb2bC3a++Cba+1bCaa

然后。。膜永刚大佬说这相当于,两堆球,一堆a个一堆b个,从里面一共取出b+1个的取法。。结果就是 Cb+1a+b

注意组合数比较大,预处理一下逆表在计算。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=200005;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;
string ss;
int l[MAXN];
int r[MAXN];

LL fact[MAXN];
LL inv[MAXN];
LL f[MAXN];
void pre()
{
    //MOD是要模的数
    //fact是阶乘取模表,inv是阶乘的逆取模
    M(fact, 0);M(inv, 0);M(f, 0);
    const LL MOD=mod;
    fact[0]=1;
    f[0]=1;
    inv[0]=1;
    fact[1]=1;
    f[1]=1;
    inv[1]=1;
    for(int i=2;i<MAXN;i++)
    {
        fact[i]=(LL)(fact[i-1]*i)%MOD;
        f[i]=(LL)(MOD-MOD/i)*f[MOD%i]%MOD;
        inv[i]=(LL)inv[i-1]*f[i]%MOD;
    }
}

LL CMOD(LL a, LL b)
{
    if(b>a) return 0;
    if(b==a) return 1;
    LL res=0;
    res=(((fact[a]*inv[b])%mod)*inv[a-b])%mod;
    return res;
}



int main()
{
    _;
    pre();
    M(l, 0);M(r, 0);
    while(cin>>ss)
    {
        int n=ss.size();
        int pre=0;
        for(int i=0;i<n;i++)
        {
            if(ss[i]==')')
            {
                l[i]=pre;
            }
            else pre++;
        }
        pre=0;
        for(int i=n-1;i>=0;i--)
        {
            if(ss[i]==')')
            {
                r[i]=pre;pre++;
            }
        }

        LL sum=0;
        for(int i=0;i<n;i++)
        {
            if(ss[i]==')')
            {
                sum=(sum+CMOD(l[i]+r[i], r[i]+1))%mod;
            }
        }
        cout<<sum<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值