比赛链接:https://ac.nowcoder.com/acm/contest/1221
好难,就拿了一些水题分
f ( i ) f(i) f(i)表示 i i i的最小质因子,求 ∑ i = 2 n f ( i ) \sum_{i=2}^nf(i) ∑i=2nf(i)
线性筛就是用每个数的最小质因子把这些数筛掉,所以筛的时候统计就好了
#include
#include
#include
#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);
}
对于一个字符串的子串的价值是在其他字符串里有多少个和它相同的子串。
给 n n n个字符串,每次询问第 x x x个字符串长度为 l e n len len的子串的价值之和是多少
我们发现每个字符串的长度都很小,所以我们可以暴力字符串 h a s h + m a p hash+map hash+map库来统计
要注意的是不能算上自己这个字符串,所以每次询问时在开一个 m a p map map,再用两个相减
#include
#include
#include
#include
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);
}
}
将 n n n个数分为 k k k组,每组的价值是最大的数减去最小的数。求最大价值和
显然我们可以贪心选取,需要注意的是若 k > n 2 k>\frac{n}{2} k>2n,那么有些就得单独一组
#include
#include
#include
#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);
}
求四个点能不能组成正方形,或者微调之后能不能组成正方形。
考试的时候直接匹配了 4 4 4条边相等(没有判断菱形)就过了,如果要判断菱形就加一个判断对角线是不是边长的 2 \sqrt2 2倍就好了,这里就不加先了
#include
#include
#include
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");
}
一个三维空间以 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)为中心,每次两个操作
因为是 k k k的最小整数值,所以我们直接对于小数向上取整,然后二分+树状数组即可
#include
#include
#include
#include
#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);
}
}
}