EOJ Monthly 2019.9 题解
C题
本题是个思维暴力题
因为受到的伤害是固定的,所以问题不在于哪个时机 Cuber QQ 打出最后一击,而是是否能在每次外界攻击前配合之前的攻击打死小兵,我们只需要在这次攻击结算前一秒打出最后一击就行了。
而要求第一下最晚,就恰好是从 ans 到 ai−1 (也就是这次攻击结算前一秒) 恰好一直连续攻击 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; }
D题
我们只关心鸭子是否分布在一个半圆中,所以鸭子离圆心的距离不重要。我们可以假设鸭子都落在圆周上。
如果所有的鸭子分布在同一个半圆中,那么让鸭子面朝圆心,所有的鸭子一定都在某一只鸭子的右手边。
令所有鸭子都在第 i 只鸭子的右手边是事件 Pi,则 Pi 发生的概率是 2^1−n。那么,n 只鸭子分布在其中任何一只鸭子的右手边的概率是不是 n⋅2^1−n ?
答案是肯定的。可以证明 Pi 和 Pj (i≠j) 不会同时发生(因为 n 只鸭子不会同时分布在 i 和 j 的右手边,如果 i 在 j 的右手边,j 就一定在 i 的左手边)。对于 n 个不会同时发生的事件,它们之中任何一个发生的的概率就是每一个发生的概率之和,也就是说,n 只鸭子分布在其中任何一只鸭子的右手边的概率是 n⋅2^1−n。
因此,n 只鸭子分布在同一个半圆中的概率就是 n⋅2^1−n。
另外本题有很多注意点:
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; } }