题出的好!难度适中,覆盖知识点广,题目又着切合实际的背景,解法比较自然。给出题人点赞 !
然而我太菜了,只会8/13,差不多一半不会
A: 文远知行β
题目加粗,n个时刻速度均大于0.
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int t,n;
int main()
{
cin>>t;
while(t--)
{
bool ok=1;
int x;
cin>>n;
for(int i=1;i<=n;i++){cin>>x;if(!x)ok=0;}
if(ok)puts("WeRide.ai");
else puts("Transform Mobility With Autonomous Driving");
}
return 0;
}
B: 学姐是野兔先辈β
原来是0不变,原来非0一半概率x-lowbit(x),一半概率x+lowbit(x),期望还是x,因此不管怎么操作答案就是原数列的值。
所以用前缀和就出来了。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int t,n,m,a[100005];
char type[105],name[105];
int l,r,num;
int sum[100005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sum[1]=a[1];
for(int i=2;i<=n;i++)sum[i]=sum[i-1]+a[i];
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&num,&l,&r);
if(num==2)
{
printf("%d\n",sum[r]-sum[l-1]);
}
}
}
return 0;
}
C: 名为青春的悖论β
以一个点为基准点,用一个数组s[]记录每个点与基准点的距离,开个桶have[x]==0or1记录是否存在一个点与基准点距离为x,要形成矩形,就是选两条直径,对应的4个点一定能围成矩形,设tot为直径条数,矩形个数为c(tot,2)。
要求出tot,只需在从基准点开始的半圆内枚举每一个点,看另半个圆里是否有点与此点距离为半圆周长。如果圆周长为奇数,那么一定不存在两点位于一条直径上,因为点间距离都是整数。
复杂度o(n)
#include<iostream>
#include<cstring>
using namespace std;
int n,s[305],cir;
bool have[4505];
int main()
{
//freopen("input.in","r",stdin);
while(cin>>n)
{
memset(have,0,sizeof(have));
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]+=s[i-1];
have[s[i]]=1;
}
cir=s[n]/2;
int tot=(have[cir]);
for(int i=1;s[i]<cir;i++)if(have[s[i]+cir])tot++;
if(s[n]&1)cout<<0<<endl;
else cout<<tot*(tot-1)/2<<endl;
}
return 0;
}
D: 明日会吹明日的风?β
用gets()每次读入一行,判断第一个字符就可以知道是哪种类型了。不知道为什么开始用scanf+strcmp一直wa,感觉情况都处理到了啊。。最后一小时换成gets()马上就过了。。
//时隔一周,终于找到了错,原来在写strcmp时写的strcmp(type,"double "),double后面多了个空格。。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int t,n;
char name[100005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
int ans=0;
scanf("%d",&n);
getchar();
for(int i=1;i<=n;i++)
{
fgets(name,10000,stdin);
if(name[0]=='i')ans+=4;
else if(name[0]=='f')ans+=4;
else if(name[0]=='d')ans+=8;
else if(name[0]=='l')ans+=8;
else if(name[0]=='c')ans+=1;
else if(name[0]=='b')ans+=1;
}
if(ans%1024==0)printf("%d\n",ans/1024);
else printf("%d\n",(ans/1024+1));
}
return 0;
}
E: 把所有的谎言献给你β
把一个自然数划分为若干个不重复的数的和,使这些数之积最大。
首先,如果是把x划分为n份,可以每份相等,则乘积最大时每份都是x/n。(a+1)(a-1)=a*a-1,可以这么不准确地理解一下。自己对数字很不敏感,开始时认为乘积最大对应的每份都不相等,实际上是相等的。
划分的每份相等,那么划分多少次呢?如果不要求每份为整数,答案是每份为e,划分为x/e份。
推导见图:把k划分为n份
那么,如果是把一个自然数划分为若干个可重复的数的和,使这些数之积最大,只需根据x%3,尽可能多划分出3,剩下的划分为2.
把一个自然数划分为若干个不重复的数的和,使这些数之积最大。对于这个问题,详尽的思路参考这篇bloghttps://blog.csdn.net/u012879957/article/details/82382460
大体意思就是依次拆成2,3,4,5......k剩下的不能k+1的放到2~k之上。
#include<iostream>
using namespace std;
int main()
{
int t,n;
cin>>t;
while(t--)
{
long long ans=1;
cin>>n;
int k=2;
while((2+k+1)*(k-1+1)/2<=n)k++;
int t=k-(n-(2+k)*(k-1)/2)+1;
for(int i=2;i<=k;i++)ans*=(i<t?i:i+1);
if(t==1)ans=ans/(k+1)*(k+2);
if(n==1)cout<<"1 1\n";
else if(n==2)cout<<"2 2\n";
else cout<<n-1<<" "<<ans<<"\n";
}
return 0;
}
F: 那天的延长线在今天β
模拟
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int t,n,a[10005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int ans=1;
int pos=2;
while(pos<=n)
{
int i;
for(i=pos;i<=n;i++)
{
if(a[i]!=a[i-1]+1)break;
}
ans=max(ans,i-pos+1);
pos=i;
pos++;
}
printf("%d\n",ans);
}
return 0;
}
G: 活在无尽梦境的后续 β
围成半圆
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define pi (acos(-1))
int t,n,m,a[100005];
char type[105],name[105];
int l,r,num;
int sum[100005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%f\n",n*n/pi/2);
}
return 0;
}
H: 以行走般的速度β
参考样例,自己手推,原数字与另一个数字互相正负转化4次后,回到原数字。因为转换后就不能再使用这个转换方式了,以n=6为例,2-4是4*2=8,2-6是4*3=12,3-6是4*2=8,其余2~6每个数字本身正负转换一次答案是33。可以假设每个数转化为它的所有因数一次,它的因数不转化为它。这样就是4-2,6-2,6-3,其余正负转化。
用这样的思路预处理就好了。
#include<cstdio>
using namespace std;
long long n,a[100005];
int main()
{
for(int i=2;i<=100000;i++)a[i]=1;
for(int i=2;i<=50000;i++)
{
for(int j=i*2;j<=100000;j+=i)
{
a[j]+=4*j/i;
}
}
for(int i=3;i<=100000;i++)a[i]+=a[i-1];
while(~scanf("%lld",&n))printf("%lld\n",a[n]);
return 0;
}
I: 灰暗而空虚的景色β
三个要点:
1.假设有3个数:i<j<k,题目从前往后是jik,则先处理j,后处理i,和不处理j是一样的,处理完i,处理k,i~k由第二次操作确定,k~n由第三次操作确定。故从后往前看,只有当前处理的位置比后面处理的位置靠左边才做处理。
2. 1^2+2^2+3^2+......+n^2==n*(n+1)*(2*n+1)/6
3.x/y%k==x%(y*k)/y
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int t,n,q;
int query[100005];
long long ans;
long long fac(long long n)
{
long long ret=1;
ret=ret*n%(6*123456789);
ret=ret*(n+1)%(6*123456789);
ret=ret*(2*n+1)%(6*123456789);
ret/=6;
return ret;
}
int main()
{
// freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
ans=0;
scanf("%d%d",&n,&q);
for(int i=1;i<=q;i++)scanf("%d",&query[i]);
long long last=n+1,pos=q,num=(1<<30);
while(pos>=1)
{
if(query[pos]>=num)pos--;
else
{
ans+=fac(last-query[pos]);
ans%=123456789;
last=query[pos];
num=query[pos];
pos--;
}
}
printf("%lld\n",ans);
}
return 0;
}
J: 温柔的手彼此相系β
将电话号码标准化为数字或者字符串,用map<string,int>或map<int,int >来存,最后遍历时因为map本身就是按照key排序的,因此直接遍历一遍map就好了。比赛时忘了这个性质,用了好多东西,代码又臭又长。
自己是标准化为数字,这样就要注意电话号码第一位或者第四位为0时,输出要补0,直接输出的话就空了一位,好在最后一个小时终于看出来了。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<cctype>
#include<map>
using namespace std;
int n,cnt[100005];
vector<int> v,ans;
map<int,int> vis;
int num[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9,0};
char s[1005];
int to[100005];
bool cmp(int x,int y)
{
return ans[x]<ans[y];
}
int main()
{
//freopen("input.in","r",stdin);
while(scanf("%d",&n)!=EOF)
{
vis.clear();
ans.clear();
memset(cnt,0,sizeof(cnt));
while(n--)
{
v.clear();
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++)if(s[i]!='-')
{
if(isdigit(s[i]))v.push_back(s[i]-'0');
else v.push_back(num[s[i]-'A']);
}
int number=0;
for(int i=0;i<7;i++)number=number*10+v[i];
if(vis.count(number))
{
for(int i=0;;i++)
{
if(ans[i]==number)
{
cnt[i]++;
break;
}
}
}
else
{
ans.push_back(number);
cnt[ans.size()-1]++;
vis[number]=1;
}
}
n=ans.size();
for(int i=0;i<n;i++)to[i]=i;
sort(to,to+n,cmp);
bool ok=0;
for(int i=0;i<n;i++)if(cnt[i]>1)ok=1;
if(!ok)printf("No duplicates.\n");
else
for(int i=0;i<n;i++)
{
int pos=to[i];
if(cnt[pos]==1)continue;
printf("%03d-%04d %d\n",ans[pos]/10000,ans[pos]%10000,cnt[pos]);
}
}
return 0;
}
K: Complex Congratulation β
题目两个要求
1.影响力之和越大越好(恰好每个影响力都非负)
2.至少一半的人支持A&&至少一半的人支持B
既支持a又支持b的对1有好处又对2有好处,全部选中。支持1的和支持2的成对选中,对1有好处,对2没影响。剩下的光支持一方但无法配对的和都不支持的选中影响力最大的k个人,k=同时支持ab的人数。
#include<cstdio>
#include<algorithm>
using namespace std;
int n,ab,a,b,no,ans;
int power[4][400005];
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
//freopen("input.in","r",stdin);
int x,y;
while(scanf("%d",&n)!=EOF)
{
ans=ab=a=b=no=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
if(x==11){ab++;power[0][ab]=y;}
else if(x==10){a++;power[1][a]=y;}
else if(x==1){b++;power[2][b]=y;}
else {no++;power[3][no]=y;}
}
for(int i=1;i<=ab;i++)ans+=power[0][i];
sort(power[a>b?1:2]+1,power[a>b?1:2]+1+(a>b?a:b),cmp);
for(int i=1;i<=min(a,b);i++)ans+=power[1][i]+power[2][i];
for(int i=min(a,b)+1;i<=(a>b?a:b);i++)power[3][++no]=power[a>b?1:2][i];
sort(power[3]+1,power[3]+1+no,cmp);
for(int i=1;i<=ab;i++)ans+=power[3][i];
printf("%d\n",ans);
}
return 0;
}
L: 只有我不在的世界β
lcm/a==b/gcd,故数量==b/gcd的个数==gcd的个数,枚举就行了。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define pi (acos(-1))
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int t,n,m,a[100005];
char type[105],name[105];
int l,r,num;
int sum[100005];
int cnt[1005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
int tot=0;
memset(cnt,0,sizeof(cnt));
scanf("%d",&n);
for(int i=1;i<=1000;i++)
{
int ans=gcd(n,i);
if(!cnt[ans])
{
cnt[ans]=1;
tot++;
}
}
printf("%d\n",tot);
}
return 0;
}
M: 在那天的雪停息之前β
模拟
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int t,n,m,a[100005];
char type[105],name[105];
int l,r,num;
int sum[100005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
while(n!=1)
{
if(n&1)
{
printf("%d*3+1=%d\n",n,3*n+1);n=n*3+1;
}
else
{
printf("%d/2=%d\n",n,n/2);n=n/2;
}
}
if(t)puts("");
}
return 0;
}