zoukankan      html  css  js  c++  java
  • EOJ Monthly 2019.9 题解

    C题

    本题是个思维暴力题

    因为受到的伤害是固定的,所以问题不在于哪个时机 Cuber QQ 打出最后一击,而是是否能在每次外界攻击前配合之前的攻击打死小兵,我们只需要在这次攻击结算前一秒打出最后一击就行了。

    而要求第一下最晚,就恰好是从 ansai1 (也就是这次攻击结算前一秒) 恰好一直连续攻击 x 次配合外界攻击击杀小兵,显然这样是可行的又是最好的方案。注意需要过滤掉超过 108 的攻击,或者干脆加一个时间为 108+1,伤害为 n 的攻击。

    然后就是从小到大枚举每次攻击前一秒,看看是否可以给出最后一击,然后更新答案。注意时间可能相等,需要一次处理完所有 ai 相同的攻击,也要注意随之而来的爆 int 问题。

    本题坑点有如下(我全踩了,怒wa3小时):

    1.注意精度问题

    2.注意删除大于1e8的时间,我做错的原因是,直接把第一个存进去了,忘记第一个也可能是大于1e8,不过一般人应该不会跟我的傻做法一样

    3.计算时间时,应该用时间-(总血量-1)/战斗力*冷却时间,因为如果血量和战斗力相同,在最后一秒就行。

    4.注意要对相同时间的攻击叠加处理,并且如果所有攻击用完还有血量,直接从1e8往前减就行

    5.因为我是按照题解写的,并根据wa点数据找到自己的漏洞,所以我的代码并不精简,应当进行优化,然而这题写了3个小时,就懒得优化了

    #include<cstring>
    #include<string>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<cstdio>
    #include <unordered_map>
    using namespace std;
    typedef long long ll;
    const int N=1e6+10;
    const ll mod=1e9+7;
    int a[N],b[N];
    ll c[N],d[N];
    int main(){
        ll res=-1;
        ll n,m,t,s;
        cin>>n>>m>>s>>t;
        int i;
        for(i=1;i<=m;i++){
            scanf("%d%d",&a[i],&b[i]);
        }
        int cnt=0;
        if(a[1]<=1e8){
        cnt++;
        c[1]=a[1];
        d[1]=b[1];
        }
        for(i=2;i<=m;i++){
            if(a[i]>1e8)
            continue;
            while(a[i]==c[cnt]){
                d[cnt]+=b[i];
                i++;
            }
            if(i>m)
            break;
            cnt++;
            c[cnt]=a[i];
            d[cnt]=b[i];
        }
        for(i=1;i<=cnt;i++){
            ll tmp=c[i]-1;
            if(tmp<t){
                tmp+=t;
                if(tmp/t*s>=n)
                res=c[i]-1;
            }
            else{
            if(tmp/t*s>=n){
                res=tmp-(n-1)/s*t;
            }}
            n-=d[i];
            if(n<=0)
            break;
        }
    
        if(i>cnt){
            res=1e8-(n-1)/s*t;
            if(res<0)
            res=-1;
        }
        cout<<res<<endl;
    }
     
    View Code

    D题

    我们只关心鸭子是否分布在一个半圆中,所以鸭子离圆心的距离不重要。我们可以假设鸭子都落在圆周上。

    如果所有的鸭子分布在同一个半圆中,那么让鸭子面朝圆心,所有的鸭子一定都在某一只鸭子的右手边。

    令所有鸭子都在第 i 只鸭子的右手边是事件 Pi,则 Pi 发生的概率是 2^1n。那么,n 只鸭子分布在其中任何一只鸭子的右手边的概率是不是 n2^1n

    答案是肯定的。可以证明 PiPj (ij) 不会同时发生(因为 n 只鸭子不会同时分布在 ij 的右手边,如果 ij 的右手边,j 就一定在 i 的左手边)。对于 n 个不会同时发生的事件,它们之中任何一个发生的的概率就是每一个发生的概率之和,也就是说,n 只鸭子分布在其中任何一只鸭子的右手边的概率是 n2^1n

    因此,n 只鸭子分布在同一个半圆中的概率就是 n2^1n

    另外本题有很多注意点:

    1.用快速幂求逆元,因为p是素数

    2.对输入的n需要提前%p,防止爆long long

    3.一个小知识点,虽然题目要求是要最简真分数,但是我们直接求逆元并mod就可以得出正确答案。

    4.做幂运算时,调用库函数会爆long long,因此要用快速幂求。

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<cstdio>
    #include <unordered_map>
    using namespace std;
    typedef long long ll;
    const int N=110;
    const ll mod=1e9+7;
    ll gcd(ll a,ll b){
        return b?gcd(b,a%b):a;
    }
    ll qmi(ll m,ll k){
        ll res=1%mod;
        ll t=m%mod;
        while(k){
            if(k&1){
                res=res*t%mod;
            }
            t=t*t%mod;
            k>>=1;
        }
        return res%mod;
    }
    int main(){
        ll n;
        int t;
        cin>>t;
        ll res=0;
        while(t--){
            cin>>n;
            if(n<=2)
              res=1;
            else{
                ll tmp=qmi(2,n-1);
                n%=mod;
                res=n*qmi(tmp,mod-2)%mod;
            }
            cout<<res<<endl;
            
            
        }
    }
     
    View Code
  • 相关阅读:
    LeetCode
    <OFFER15> 15_NumberOf1InBinary
    《OFFER14》14_CuttingRope
    Convert DataFrame string complex i to j python // “Cloning” row or column vectors
    Sorting arrays in NumPy by column
    【説明する】深度优先及宽度优先算法比较
    codevs 2924 数独挑战 x(三种做法+超详细注释~)
    第四次考试大整理
    洛谷 P1048 采药
    codevs 3137-3139 栈练习 x
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12204532.html
Copyright © 2011-2022 走看看