正题
比赛链接:https://ac.nowcoder.com/acm/contest/1221
成绩
总结
好难,就拿了一些水题分
T1:Forsaken喜欢数论\texttt{T1:Forsaken喜欢数论}T1:Forsaken喜欢数论
题目大意
f(i)f(i)f(i)表示iii的最小质因子,求∑i=2nf(i)\sum_{i=2}^nf(i)∑i=2nf(i)
解题思路
线性筛就是用每个数的最小质因子把这些数筛掉,所以筛的时候统计就好了
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll n,cnt,prime[6893911*3],ans;
bool v[10000001*3];
int main()
{scanf("%lld",&n);v[1]=1;for(ll i=2;i<=n;i++){if(!v[i]) prime[++cnt]=i,ans+=i;for(ll j=1;j<=cnt&&i*prime[j]<=n;j++){v[prime[j]*i]=1;ans+=prime[j];if(!(i%prime[j])) break;}}printf("%lld",ans);
}
T2:Forsaken喜欢字符串\texttt{T2:Forsaken喜欢字符串}T2:Forsaken喜欢字符串
题目大意
对于一个字符串的子串的价值是在其他字符串里有多少个和它相同的子串。
给nnn个字符串,每次询问第xxx个字符串长度为lenlenlen的子串的价值之和是多少
解题思路
我们发现每个字符串的长度都很小,所以我们可以暴力字符串hash+maphash+maphash+map库来统计
要注意的是不能算上自己这个字符串,所以每次询问时在开一个mapmapmap,再用两个相减
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=5e4+10;
int n,k,m;
map<int,int> v,now;
char s[N][6];
int main()
{scanf("%d%d",&n,&k);for(int i=1;i<=n;i++){scanf("%s",s[i]);for(int l=0;l<k;l++){int z=0;for(int r=l;r<k;r++){z+=s[i][r]-'a'+1;z*=27;v[z]+=r-l+1;}}}scanf("%d",&m);while(m--){int x,len;scanf("%d%d",&x,&len);now.clear();int ans=0;for(int l=0;l<k;l++){int z=0;for(int r=l;r<k;r++){z+=s[x][r]-'a'+1;z*=27;now[z]+=r-l+1;}}for(int l=0;l<k;l++){int z=0;if(l+len>k) continue;for(int r=l;r<min(l+len,k);r++)z+=s[x][r]-'a'+1,z*=27;ans+=v[z]-now[z];}printf("%d\n",ans);}
}
T3:Forsaken给学生分组\texttt{T3:Forsaken给学生分组}T3:Forsaken给学生分组
题目大意
将nnn个数分为kkk组,每组的价值是最大的数减去最小的数。求最大价值和
解题思路
显然我们可以贪心选取,需要注意的是若k>n2k>\frac{n}{2}k>2n,那么有些就得单独一组
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,k,a[N],ans;
int main()
{scanf("%lld%lld",&n,&k);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);sort(a+1,a+1+n);if(k>n/2) k=n-k;for(ll i=1;i<=k;i++)ans+=a[n-i+1]-a[i];printf("%lld",ans);
}
T4:Forsaken喜欢正方形\texttt{T4:Forsaken喜欢正方形}T4:Forsaken喜欢正方形
题目大意
求四个点能不能组成正方形,或者微调之后能不能组成正方形。
解题思路
考试的时候直接匹配了444条边相等(没有判断菱形)就过了,如果要判断菱形就加一个判断对角线是不是边长的2\sqrt22倍就好了,这里就不加先了
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int x[5],y[5];
const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int get_dis(int a,int b)
{return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);}
bool check()
{int l1=get_dis(1,2),l2=get_dis(2,3),l3=get_dis(3,4),l4=get_dis(4,1);if(l1==l2&&l2==l3&&l3==l4) return 1;l1=get_dis(1,2),l2=get_dis(2,4),l3=get_dis(4,3),l4=get_dis(3,1);if(l1==l2&&l2==l3&&l3==l4) return 1;l1=get_dis(1,3),l2=get_dis(3,2),l3=get_dis(2,4),l4=get_dis(4,1);if(l1==l2&&l2==l3&&l3==l4) return 1;l1=get_dis(1,3),l2=get_dis(3,4),l3=get_dis(4,2),l4=get_dis(2,1);if(l1==l2&&l2==l3&&l3==l4) return 1;l1=get_dis(1,4),l2=get_dis(4,2),l3=get_dis(2,3),l4=get_dis(3,1);if(l1==l2&&l2==l3&&l3==l4) return 1;l1=get_dis(1,4),l2=get_dis(4,3),l3=get_dis(3,2),l4=get_dis(2,1);if(l1==l2&&l2==l3&&l3==l4) return 1;return 0;
}
int main()
{for(int i=1;i<=4;i++)scanf("%d%d",&x[i],&y[i]);if(check()){printf("wen");return 0;}for(int i=1;i<=4;i++){for(int k=0;k<4;k++){x[i]+=dx[k];y[i]+=dy[k];if(check()){printf("hai xing");return 0;}x[i]-=dx[k];y[i]-=dy[k];}}printf("wo jue de bu xing");
}
T7:Forsaken的三维数点\texttt{T7:Forsaken的三维数点}T7:Forsaken的三维数点
题目大意
一个三维空间以(0,0,0)(0,0,0)(0,0,0)为中心,每次两个操作
- 加入一个能量球在(x,y,z)(x,y,z)(x,y,z)
- 以中心半径为kkk的球能够包括xxx个能量球,求kkk的最小整数值
解题思路
因为是kkk的最小整数值,所以我们直接对于小数向上取整,然后二分+树状数组即可
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define lowbit(x) x&-x
using namespace std;
const int N=2e5+10;
int n,t[N+10],l,r;
void change(int x,int z)
{while(x<=N){t[x]+=z;x+=lowbit(x);}
}
int ask(int x)
{int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;
}
double get_dis(double x,double y,double z)
{return sqrt(x*x+y*y+z*z);}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){int op;double x,y,z;scanf("%d%lf",&op,&x);if(op==1){scanf("%lf%lf",&y,&z);double dis=get_dis(x,y,z);dis+=(((int)dis)!=dis);change((int)dis,1);}else{l=0;r=N;while(l<=r){int mid=(l+r)/2;if(ask(mid)<(int)x) l=mid+1;else r=mid-1;}if(ask(l)<(int)x) printf("-1\n");else printf("%d\n",l);}}
}