A-Forsaken喜欢数论
线性筛水题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int N=3e7+10;
int pre[N],p[N];
vector<int>prime;
int n;
void get_p()
{
int h=0;
for(int i=2;i<=n;i++)
{
if(p[i]==0)
{
prime.pb(i);
pre[i]=i;
}
for(int j=0;j<prime.size()&&i*prime[j]<N;j++)
{
pre[i*prime[j]]=prime[j];
p[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
ll sum[N];
int main()
{
scanf("%d",&n);
get_p();
ll ans=0;
for(int i=1;i<=n;++i) ans+=pre[i];
printf("%lld\n",ans);
}
B-Forsaken喜欢字符串
hash统计一下就可以了。。水题加1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+10;
ll base[3]={43,47};
ll h[3][N][10];
ll mod[3]={1000000007,998244353};
ll f[3][N];
int n,k;
const int M=5e4+10;
char s[M][10];
map<pair<int,int>,int>mp;
void init()
{
f[0][0]=1;
f[1][0]=1;
for(int i=1;i<N;++i)
{
for(int j=0;j<2;++j) f[j][i]=f[j][i-1]*base[j]%mod[j];
}
}
pair<int,int> getv(int id,int l,int r)
{
pair<int,int>p;
int d1=(h[0][id][r]-h[0][id][l-1]*f[0][r-l+1]%mod[0]+mod[0])%mod[0];
int d2=(h[1][id][r]-h[1][id][l-1]*f[1][r-l+1]%mod[1]+mod[1])%mod[1];
p=make_pair(d1,d2);
return p;
}
int getid(char c)
{
return c-'0';
}
int main()
{
init();
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%s",s[i]+1);
for(int j=1;j<=k;++j)
{
for(int k=0;k<2;++k)
{
h[k][i][j]=h[k][i][j-1]*base[k]%mod[k]+getid(s[i][j]);
}
}
for(int r=1;r<=k;++r)
{
for(int l=1;l<=r;++l)
{
pair<int,int>p;
p=getv(i,l,r);
mp[p]++;
}
}
}
int q;
scanf("%d",&q);
while(q--)
{
int id,len;
ll ans=0;
scanf("%d%d",&id,&len);
for(int r=1;r<=k;++r)
{
for(int l=1;l<=r;++l)
{
pair<int,int>p;
p=getv(id,l,r);
mp[p]--;
}
}
for(int i=1;i+len-1<=k;++i)
{
pair<int,int>p;
p=getv(id,i,i+len-1);
//printf("l:%d r:%d mp:%d\n",i,i+len-1,mp[p]);
ans+=1ll*mp[p]*len;
}
for(int r=1;r<=k;++r)
{
for(int l=1;l<=r;++l)
{
pair<int,int>p;
p=getv(id,l,r);
mp[p]++;
}
}
printf("%lld\n",ans);
}
}
/*
3 4
abab
abab
abab
100
3 1
*/
C-Forsaken给学生分组
排个序,取前k个最大的和前k个最小的放在一起即可。。水题+1
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
int a[N];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
ll ans=0;
for(int i=1,j=n;i<=k;++i,--j){
ans+=a[j]-a[i];
}
printf("%lld\n",ans);
}
D-Forsaken喜欢正方形
注意这里不算规规矩矩的正方形,我想当然了,wa自闭了。
然而这里我判断了三条边的长度是否相等就A了,菱形是hack数据,应该还要判断一个角是90度角
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
struct node
{
int x,y;
}B[5];
vector<node>a[5];
bool cmp(node a,node b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
int dis(node a,node b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cal(node a,node b,node c,node d)
{
node A[5];
A[1]=a;A[2]=b;A[3]=c;A[4]=d;
sort(A+1,A+1+4,cmp);
if(dis(A[1],A[2])==dis(A[1],A[3])&&dis(A[1],A[2])==dis(A[4],A[2]))
return 1;
/*
if(A[1].x==A[2].x&&A[1].y==A[3].y)
if(A[2].y==A[4].y&&A[3].x==A[4].x)
if(A[4].x-A[2].x==A[4].y-A[3].y)
if(A[4].x-A[2].x==A[2].y-A[1].y)
return 1;*/
return 0;
}
int dir[4][2]={1,0,0,1,-1,0,0,-1};
int main()
{
for(int i=1;i<=4;++i) scanf("%d%d",&B[i].x,&B[i].y);
if(cal(B[1],B[2],B[3],B[4])) {
printf("wen\n");
return 0;
}
for(int j=1;j<=4;++j){
for(int i=0;i<4;++i){
B[j].x+=dir[i][0];B[j].y+=dir[i][1];
if(cal(B[1],B[2],B[3],B[4])){
printf("hai xing\n");
return 0;
}
B[j].x-=dir[i][0];B[j].y-=dir[i][1];
}
}
printf("wo jue de bu xing\n");
}
/*
1 1
2 1
1 3
2 3
*/
G-Forsaken的三维数点
二分加树状数组即可。。。水题+1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n;
int sum[N];
int lowbit(int x)
{
return x&(-x);
}
void add(int x)
{
for(int i=x;i<N;i+=lowbit(i)) sum[i]++;
}
int qu(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i))res+=sum[i];
return res;
}
int main()
{
scanf("%d",&n);
int mx=0;
for(int i=1;i<=n;++i)
{
int op;
scanf("%d",&op);
if(op==1){
ll x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
double dis=sqrt(1ll*x*x+y*y+z*z);
dis+=(((int)dis)!=dis);
add((int)dis);
//printf("dis:%d\n",(int)dis);
}
else{
ll k;
scanf("%lld",&k);
int l=0,r=N;
int ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(qu(mid)>=k){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
printf("%d\n",ans);
}
}
}
H-Forsaken喜欢独一无二的树
这题有点巧妙,来看官方题解:
第一种不知道是什么鬼操作。。
来看第二种。
我只需要加上所有权值相等且之前不在最小生成树内的边,去掉能被最小生成树覆盖的边即可。。。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
struct node
{
int u,v,w;
}e[N];
int n,m;
int fa[N];
bool cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
for(int i=1;i<=n;++i) fa[i]=i;
sort(e+1,e+1+m,cmp);
ll ans=0;
for(int l=1;l<=m;)
{
int r=l;
while(e[r].w==e[l].w&&r<=m)++r;
--r;
for(int i=l;i<=r;++i)
{
int f1=find(e[i].u);
int f2=find(e[i].v);
if(f1!=f2) ans+=e[i].w;
}
for(int i=l;i<=r;++i)
{
int f1=find(e[i].u);
int f2=find(e[i].v);
if(f1!=f2) fa[f1]=f2,ans-=e[i].w;
}
l=r+1;
}
printf("%lld\n",ans);
}