杭二集训 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;
}