杭二集训 2019.8.17

T1

题目意思:给出l,r,p,求区间[l,r]之间有多少数的最小质因子是p。

数据范围:1<=l<=r<=1000000000,1<=p<=1000000000

Solution:

考虑设\(f(x,y)\)表示从1到\(x\)中最小质因子为\(y\)的数的个数,则有

\[f(x,y)=\lfloor {x\over y} \rfloor -\sum_{k=2,k\in pri}^{min(\lfloor {x\over y} \rfloor,y-1)} f(\lfloor {x\over y} \rfloor,k) \]

其中\(pri\)为质数集合,特别的,当\(y \notin pri\)时,此函数返回0

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+1;
int L,R,P;
int isprime(int x){
	for(int i=2;i*i<=x;i++)
		if(x%i==0) return 0;
	return 1;
}
int calc(int x,int p){
	if(!isprime(p)) return 0;
	int v=x/p,re=0;
	for(int i=2;i<=min(p-1,v);i++)
		re+=calc(v,i);
	return v-re;
}
int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
signed main(){
    L=read(),R=read(),P=read();
	printf("%lld\n",calc(R,P)-calc(L-1,P));
	return 0;
}

T2

题目意思:定义一个可重正整数集合是好的,当且仅当该集合中任意两个数之和不为质数。给你一个序列,希望你从中取出一个尽量大的好的集合。

数据范围:N<=3000,1<=hi<=100000

Solution:

我们知道,除了2以外的质数都是奇数,而只有奇数+偶数=奇数

则我们考虑将集合分为奇数和偶数,将和为质数的两个数连边,然后网络流最小割

在此之前特判一下2的情况就行了

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=3003;
const int M=2e5+1;
const int inf=1947483647;
int ans,n,cnt=1,head[N],a[N],cur[N];
int S,T,pos,tot,vis[M],pri[M];
struct Edge{int nxt,to,v;}edge[N*N];
void prepare(){
	for(int i=2;i<=M;i++){
		if(!vis[i]) pri[++tot]=i;
		for(int j=1;j<=tot&&pri[j]*i<=M;j++){
			vis[i*pri[j]]=1;
			if(i%pri[j]==0) break;
		}
	}
}
void ins(int x,int y,int z){
	edge[++cnt].nxt=head[x];
	edge[cnt].to=y;head[x]=cnt;
	edge[cnt].v=z;
}
int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
namespace NetworkFlow{
	queue<int> q;
	int dep[N];
	int bfs(){
		memset(dep,0,sizeof(dep));
		q.push(S);dep[S]=1;
		while(!q.empty()){
			int x=q.front();q.pop();
			if(x==T){while(q.size()) q.pop(); return 1;}
			for(int i=head[x];i;i=edge[i].nxt)
				if(!dep[edge[i].to]&&edge[i].v){
					dep[edge[i].to]=dep[x]+1;
					q.push(edge[i].to);
				}
		}return dep[T];
	}
	int dfs(int x,int rest){
		if(x==T||rest<=0) return rest;
		int flow=0;
		for(int& i=cur[x];i;i=edge[i].nxt){
			int y=edge[i].to,v=edge[i].v;
			if(v&&dep[y]==dep[x]+1){
				int now=dfs(y,min(rest,v));
				edge[i].v-=now;
				edge[i^1].v+=now;
				flow+=now;rest-=now;
				if(rest<=0) break;
			}
		}return flow;
	}
	int dinic(){
		int maxflow=0;
		while(bfs()){
			for(int i=1;i<=n;i++)
				cur[i]=head[i];
			maxflow+=dfs(S,inf);
		}
		return maxflow;
	}
}
int main(){
	n=read();prepare();
	for(int i=1;i<=n;i++){
		a[i]=read();
		if(pos&&a[i]==1){
			i--,n--;
			continue;
		}if(a[i]==1) pos=i;
	}S=n+1,T=S+1;
	for(int i=1;i<=n;i++){
		if(!(a[i]&1)) ins(S,i,1),ins(i,S,0);
		else ins(i,T,1),ins(T,i,0);
		for(int j=i+1;j<=n;j++)
			if(!vis[a[i]+a[j]]){
				if(!(a[i]&1)) ins(i,j,1),ins(j,i,0);
				else ins(j,i,1),ins(i,j,0);
			}
	}
	int maxmatch=NetworkFlow::dinic();
	printf("%d\n",n-maxmatch);
	return 0;
}

T3

题目意思:给定一个长度为n的数列ai,求一个最长的ai的子序列bi,满足对于任意i,\(b_i\)=\(b_{i-1}\)

Solution:

QAQ

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1;
int n,ans=1,a[N];
int read(){
	int x=0,f=1;char ch=getchar();;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);int re=1;
	for(int i=2;i<=n;i++){
		if(a[i]==a[i-1]) ++re;
		else ans=max(ans,re),re=1;
	}printf("%d\n",max(ans,re));
	return 0;
}

posted @ 2019-08-22 20:16  DQY_dqy  阅读(136)  评论(0编辑  收藏  举报