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

猜你喜欢

转载自www.cnblogs.com/NLDQY/p/11396568.html