A The Fool 签到题 数论分块 数学题
B The World 时间处理问题 字符串
C Justice 思维题
E The Tower 计算几何 几何题
I Strength 贪心+田忌赛马 博弈论
A The Fool
数论分块(队友写的,所以没有解析)
# include <bits/stdc++.h>
using namespace std;
const int mod = 2;
int main(){
int t;
cin>>t;
int k = 0;
while(t--){
LL n;
cin>>n;
LL ans = 0;
for(LL l=1,r;l <= n; l = r + 1){
r = n / (n / l);
ans = (ans + (r - l + 1) * (n / l)) % mod;
}
printf("Case %d: ",++k);
if(ans) printf("odd\n");
else printf("even\n");
}
return 0;
}
B The World
这个其实是一个水题,但是有一个坑点,我当时也没注意到wa了一次,后面学长提醒才注意到就是am只的是凌晨12点到中午的11:59:59,而从下午的12点开始就是pm了,一直到晚上的11:59:59。上述也为一天的具体时间。
include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++){
int h;
string a;
string m;
string d;
string s1,s2;
cin>>h;
getchar();//独掉“:”
cin>>m;
cin>>a;
if(a=="PM"){//转化为二十四小时制
if(h!=12) h=h+12;//如果是12点的话,属于pm的只有中午12点,所以不要用转化,不太明白的可以看开头关于am,pm的解释
}
if(a=="AM"){//如果是属于am的12点就是夜里凌晨转化为0防止混淆
if(h==12) h=h-12;
}
cin>>s1;
cin>>s2;
int utc;
if(s1=="Beijing") utc=h-8;//将现在的时间转化为utc标准时间
if(s1=="Washington") utc=h+5;
if(s1=="London") utc=h;
if(s1=="Moscow") utc=h-3;
if(s2=="Beijing") h=utc+8;//将utc时间再转化为当前时间
if(s2=="Washington") h=utc-5;
if(s2=="London") h=utc;
if(s2=="Moscow") h=utc+3;
if(h<0){//判断是昨天,今天还是明天
h=h+24;
d="Yesterday";
}else if(h>=24){
h=h-24;
d="Tomorrow";
}else{
d="Today";
}
//判断是am还是pm,同时将时间转化为12小时制的
if(h>=12&&h<24){//pm的转化,注意特判12
if(h!=12) h=h-12;
a="PM";
}else if(h==0){//凌晨12点的特判
h=12;
a="AM";
}else{
a="AM";
}
cout<<"Case "<<i<<": "<<d<<" "<<h<<":"<<m<<" "<<a<<endl;
}
return 0;
}
C Justice
队友写的(所以还是没有解析,不要打我)
# include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
bool vis[maxn];
int dp[maxn];
vector<int> dict[maxn];
inline void init(){
memset(vis,0,sizeof vis);
memset(dp,0,sizeof dp);
for(int i = 0; i < maxn; ++i)
dict[i].clear();
}
int main(){
int t;
cin>>t;
int k = 0;
while(t--){
int n;
cin>>n;
init();
LL tt;
for(int i = 1; i <= n; ++i){
tt;
cin>>tt;
if(tt < maxn){
dp[tt]++;
dict[tt].push_back(i);
}
}
printf("Case %d: ",++k);
for(int i = maxn - 1; i >= 2; --i){
dp[i - 1] += dp[i] / 2;
}
if(dp[1] < 2){
printf("NO\n");
continue;
}
LL sum = 1;
for(int i = 1; i <= n; ++i,sum <<= 1){
if(sum <= dict[i].size()){
for(int j = 0; j < sum; ++j){
vis[dict[i][j]] = 1;
}
break;
}
else{
for(int j = 0; j < dict[i].size(); ++j){
vis[dict[i][j]] = 1;
}
sum -= dict[i].size();
}
}
printf("YES\n");
for(int i = 1; i <= n; ++i){
printf("%d",vis[i] ? 1 : 0);
}
printf("\n");
}
return 0;
}
E The Tower
# include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
int ccase=0;
scanf("%d",&T);
while(T--){
double r,h;
double a,b,c;
double x0,y0,z0,vx,vy,vz;
double ans1=0.0,ans2=0.0,ans=1e18;
scanf("%lf %lf",&r,&h);
scanf("%lf %lf %lf",&x0,&y0,&z0);
scanf("%lf %lf %lf",&vx,&vy,&vz);
a=h*h*vx*vx+h*h*vy*vy-vz*vz*r*r;
b=2*h*r*r*vz+2*h*h*x0*vx+2*h*h*y0*vy-2*z0*vz*r*r;
c=-(h*h*(r*r-x0*x0-y0*y0)+r*r*z0*z0-2*h*r*r*z0);
//cout<<"@@@@"<<a<<" "<<b<<" "<<c<<endl;
ans1=(-b+sqrt(b*b-4*a*c))/(2.0*a);
ans2=(-b-sqrt(b*b-4*a*c))/(2.0*a);
//cout<<"####"<<ans1<<" "<<ans2<<endl;
if(ans1>0){
double tz=z0+ans1*vz;
if(tz>=0&&tz<=h){
ans=min(ans1,ans);
}
}
if(ans2>0){
double tz=z0+ans2*vz;
if(tz>=0&&tz<=h){
ans=min(ans2,ans);
}
}
double t=-z0/vz;
double tx=x0+vx*t,ty=y0+vy*t;
if((tx*tx+ty*ty)<=r*r){
ans=min(ans,t);
}
printf("Case %d: %.10f\n",++ccase,ans);
}
return 0;
}
I Strength
【思路】就是先对是否要用己方(假设我们是Alice 对方是Bob)的小怪物去处理对方的防御性的小怪物,处理掉的话,那么是为了剩下来的小怪物(除了和攻击性的打)能够产生全部的贡献(就是全部都是伤害),如果不处理是为了和攻击性的小怪物产生最大的差
对每一次查询,先判断是否能够全部都用小怪物打掉,如果能,那么就用最小的代价把防御性的对方的小怪物处理掉(因为防御性的不对结果产生贡献)然后剩下的相加减去对方攻击性的小怪物就是该种情况的最大伤害;那么不管是不是可以都把对方的小怪物处理掉,都要只对对方攻击性的小怪物贪心一次,就是用当前最大的去和对方最小的去打,那么两者之差的求和就是该种方法的最大的伤害(类似于田忌赛马)
# include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+100;
typedef long long LL;
LL a[MAXN];
int vis[MAXN];
pair<LL,LL> b[MAXN];
int main()
{
int T;
int ccase=0;
scanf("%d",&T);
while(T--){
int n,m;
LL ans1=0,ans2=0;
LL ans=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=max(n,m);i++) a[i]=0,vis[i]=0,b[i].first=0,b[i].second=0;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=m;i++) scanf("%lld",&b[i].first);
for(int i=1;i<=m;i++) scanf("%lld",&b[i].second);
sort(a+1,a+n+1);
sort(b+1,b+m+1);
int flag1=1;//判断是否是可以全部都过
for(int i=n,j=m;i>=1&&j>=1;i--,j--){
if(a[i]<b[j].first){
flag1=0;
break;
}
}
if(flag1){//如果可以全部都过
for(int i=1,j=1;i<=n&&j<=m;){//先用最小的代价处理掉防御性的小怪物
if(b[j].second==0){
j++;
}else{
if(a[i]>b[j].first){
vis[i]=1;//标记用来处理防御性的小怪物
i++,j++;
}else{
i++;
}
}
}
//for(int i=1;i<=n;i++) cout<<"%%%%"<<vis[i]<<endl;
LL sum=0,sum1=0;
for(int i=1;i<=n;i++){
if(vis[i]==0){
sum+=a[i];
}
}
for(int i=1;i<=m;i++){
if(b[i].second==0){
sum1+=b[i].first;
}
}
//cout<<"@@@"<<sum<<" "<<sum1<<endl;
ans1=sum-sum1;
}
//如果不可以全部都过,那么就对只有攻击性的贪心
int k=1;
LL sum2=0;
for(int i=n;i>=1&&k<=m;){
if(b[k].second==0){
if(a[i]>b[k].first){
sum2+=(a[i]-b[k].first);
i--;
}else{
break;
}
}
k++;
}
ans2=sum2;
ans=max(ans1,ans2);
//cout<<"@@@"<<ans1<<" "<<ans2<<endl;
printf("Case %d: %lld\n",++ccase,ans);
}
return 0;
}