A - The Fool
数论分块暴力求和
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
int main()
{
//IO;
int T=1;
cin>>T;
for(int ca=1;ca<=T;ca++)
{
int n;
cin>>n;
ll s=0;
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
s=(s+1ll*(r-l+1)%2*(n/l))%2;
}
if(s%2) printf("Case %d: odd\n",ca);
else printf("Case %d: even\n",ca);
}
return 0;
}
B - The World
这题就离谱??? 不明白下面的一二两个设定?很反直觉啊啊啊
- 12:00 AM 是凌晨十二点
- 12:00 PM 是中午十二点
- h=0输出12
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
map<string,int> mp;
int main()
{
//IO;
int T=1;
cin>>T;
mp["Beijing"] = 8;
mp["Washington"] = -5;
mp["London"] = 0;
mp["Moscow"] = 3;
for(int ca=1;ca<=T;ca++)
{
int h,m;
string op,from,to;
scanf("%d:%d",&h,&m);
cin>>op>>from>>to;
if(h==12) h=0;
if(op=="PM") h+=12;
h+=mp[to]-mp[from];
int f=0;
string now;
if(h<0)
{
f=-1;
h+=24;
}
else if(h>=24)
{
f=1;
h-=24;
}
if(h>=12)
{
h-=12;
now="PM";
}
else
now="AM";
if(h==0) h+=12;
// 输出
printf("Case %d: ",ca);
if(f==-1)
printf("Yesterday %d:%02d ", h, m);
else if(f==0)
printf("Today %d:%02d ", h, m);
else
printf("Tomorrow %d:%02d ", h, m);
cout<<now<<'\n';
}
return 0;
}
C - Justice
自己想的辣鸡代码
刚开始没思路于是想猜结论:只要和大于1就一定能够分成两组,因为它是以
1
2
k
\frac{1}{2^k}
2k1为一份,怎么分组就贪心分一下,对于较大的k由于小数太小,没法存储,我当时想的是忽略这些值(k>25的时候小数已经非常小可能对答案没影响),于是写出了下面辣鸡代码wa了
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const double eps=1e-14;
const int N=100010;
double two[110];
int ans[N];
int n;
struct node
{
int k,id;
bool operator<(const node& o) const
{
return k<o.k;
}
}q[N];
int main()
{
//IO;
int T=1;
cin>>T;
two[0]=1.0;
for(int i=1;i<=100;i++) two[i]=two[i-1]/2.0;
for(int ca=1;ca<=T;ca++)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>q[i].k;
q[i].id=i;
}
sort(q+1,q+1+n);
double s=0.0;
for(int i=1;i<=n;i++)
{
if(q[i].k>=100)
{
ans[q[i].id]=1;
continue;
}
if(s+eps>0.5)
ans[q[i].id]=1;
else
ans[q[i].id]=0;
s+=two[q[i].k];
}
if(s+eps>1.0)
{
printf("Case %d: YES\n",ca);
for(int i=1;i<=n;i++)
cout<<ans[i];
cout<<'\n';
}
else
printf("Case %d: NO\n",ca);
}
return 0;
}
正解
我们需要凑一个
1
2
\frac12
21,或者2个
1
4
\frac14
41,或者4个
1
8
…
\frac18\dots
81…
不难发现如果当前需要凑
c
n
t
cnt
cnt个
1
2
k
\frac1{2^k}
2k1,那么如果现在没有
1
2
k
\frac1{2^k}
2k1,我们不得不用
1
2
j
(
j
>
k
)
\frac1{2^j}(j>k)
2j1(j>k)来凑,不难发现我们现在需要凑
c
n
t
×
2
j
−
k
cnt×2^{j-k}
cnt×2j−k个
1
2
j
\frac1{2^j}
2j1
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=100010;
struct node
{
int k,id;
bool operator<(const node&o) const
{
return k<o.k;
}
}q[N];
int ans[N];
int n;
int main()
{
//IO;
int T=1;
cin>>T;
for(int ca=1;ca<=T;ca++)
{
cin>>n;
for(int i=1;i<=n;i++)
{
ans[i]=0;
cin>>q[i].k;
q[i].id=i;
}
sort(q+1,q+1+n);
bool ok=0;
int pre=1;
int cnt1=1,cnt2=1;
for(int i=1;i<=n;i++)
{
while(cnt1+cnt2<=n-i+1&&pre<q[i].k)//少个+1都会wa 感觉数据有点诡异啊
{
cnt1*=2;
cnt2*=2;
pre++;
}
if(cnt1+cnt2>n-i+1) break;
if(cnt1>0)
{
cnt1--;
ans[q[i].id]=1;
}
else
cnt2--;
if(cnt1<=0&&cnt2<=0)
{
ok=1;
break;
}
}
if(!ok) printf("Case %d: NO\n",ca);
else
{
printf("Case %d: YES\n",ca);
for(int i=1;i<=n;i++) cout<<ans[i];
cout<<'\n';
}
}
return 0;
}
D - The Moon
一看就是个概率dp的题,由于自己概率dp的题写的太少了,然后就写不出来,看的题解。
设
f
i
f_i
fi是当
q
=
i
q=i
q=i是的期望次数
f
i
=
p
(
1
−
q
)
(
1
+
f
q
+
2
%
)
+
p
q
+
(
1
−
p
)
(
1
+
f
q
+
1.5
%
)
f_i=p(1-q)(1+f_{q+2\%})+pq+(1-p)(1+f_{q+1.5\%})
fi=p(1−q)(1+fq+2%)+pq+(1−p)(1+fq+1.5%)
记忆化搜索即可
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=1010;
double f[N];
int p;
double dfs(int q)
{
if(f[q]>=0) return f[q];
if(q>=1000)
return f[q]=100.0/(1.0*p);
f[q]=(1.0*p/100.0)*(1.0-1.0*q/1000.0)*dfs(min(1000,q+20))
+(1.0-1.0*p/100.0)*dfs(min(1000,q+15))
+1.0;
return f[q];
}
int main()
{
//IO;
int T=1;
cin>>T;
for(int ca=1;ca<=T;ca++)
{
for(int i=0;i<=1000;i++) f[i]=-1;;
cin>>p;
printf("Case %d: %.6lf\n",ca,dfs(20));
}
return 0;
}
F - The Hermit
这题非常巧妙啊
结论:对于第
i
i
i个站
[
i
−
r
a
d
i
+
1
,
i
−
2
]
[i-rad_i+1,i-2]
[i−radi+1,i−2]范围的基站都能够接收到第
i
i
i个站的perfect signal
仔细想想可知道根据
i
−
r
a
d
i
+
1
≤
i
+
1
−
r
a
d
i
+
1
+
1
i - rad_i + 1 ≤ i + 1 - rad_{i+1} + 1
i−radi+1≤i+1−radi+1+1条件,就能使
[
i
−
r
a
d
i
+
1
,
i
−
2
]
[i-rad_i+1,i-2]
[i−radi+1,i−2]的基站满足条件。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=100010;
int main()
{
//IO;
int T=1;
cin>>T;
for(int ca=1;ca<=T;ca++)
{
int n;
cin>>n;
int res=0;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
res^=max(0,a-2);
}
printf("Case %d: %d\n", ca, res);
}
return 0;
}
I - Strength
贪心+模拟,1发A有点高兴。
先判断是否能够打死完对面的怪物,如果能够打完那么先用最小的代价把防御类型的干掉(只需找一个大于防御值的最小的攻击即可)
如果不能打死完,那么我们只需要用最大的攻击最小的即可,欺负弱小
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=100010;
int n,m;
int a[N];
int b[N];
bool st1[N],st2[N];
int main()
{
//IO;
int T=1;
cin>>T;
for(int ca=1;ca<=T;ca++)
{
memset(st1,0,sizeof st1);
memset(st2,0,sizeof st2);
vector<int> ak,df;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
for(int i=1;i<=m;i++) cin>>b[i];
for(int i=1;i<=m;i++)
{
int op;
cin>>op;
if(op) df.push_back(b[i]);
else ak.push_back(b[i]);
}
sort(df.begin(),df.end());
sort(ak.begin(),ak.end());
int cnt=0;
int j=1;
for(auto t:df)
{
while(j<=n&&a[j]<t) j++;
if(a[j]>=t)
{
st1[j]=1;
cnt++;
j++;
}
else break;
}
int res1=0,res2=0;
if(cnt==df.size())
{
int cnt=0,j=1;
for(auto t:ak)
{
while(j<=n&&!st1[j]&&a[j]<t) j++;
if(a[j]>=t)
{
res1+=a[j]-t;
j++;
st2[j]=1;
cnt++;
}
else break;
}
if(cnt==ak.size())
{
for(int i=1;i<=n;i++)
if(!st1[i]&&!st2[i]) res1+=a[i];
}
else
{
res1=0;
int j=n;
for(auto t:ak)
{
if(!st1[j]&&a[j]>=t)
{
res2+=a[j]-t;
j--;
}
else break;
}
}
}
else
{
int j=n;
for(auto t:ak)
{
if(a[j]>=t)
{
res2+=a[j]-t;
j--;
}
else break;
}
}
printf("Case %d: %d\n", ca, max(res1, res2));
}
return 0;
}
F - Lovers
线段树待补