HDU-5943-Kingdom of Obsession(杭州CCPC K题)-数学推导+匈牙利算法优化

来源:互联网 发布:nginx二级域名设置 编辑:程序博客网 时间:2024/05/30 13:41

题目链接

题意:给定一个n和s。其中,判断s+1到s+n是否存在一种匹配和1到n,两个数匹配是当前者中的数可以整除后者的数。

思路:有一个优化,若有重叠的部分,则重叠的互相抵消。(易正明,若1到n中的n不和s+1到s+n中的n匹配,则他不能其他的数匹配的),然后另一个优化也就来了,如果大的数中存在两个质数,那肯定不存在匹配。而10的9次内的素数差很小,用一个匈牙利算法匹配一下就好了。

#include<cstdio>#include<cmath>#include<iostream>#include<algorithm>#include<cstring>using namespace std;int vis[1111];int sa;int x,y,z;/**匈牙利算法板子**//****************************************************二分图匹配(匈牙利算法的DFS实现)INIT:g[][]两边定点划分的情况CALL:res=hungary();输出最大匹配数优点:适于稠密图,DFS找增广路快,实现简洁易于理解时间复杂度:O(VE);****************************************************/const int MAXN=1000;int uN,vN;  //u,v数目int g[MAXN][MAXN];//编号是0~n-1的int linker[MAXN];bool used[MAXN];bool dfs(int u){    int v;    for(v=0;v<vN;v++)        if(g[u][v]&&!used[v])        {            used[v]=true;            if(linker[v]==-1||dfs(linker[v]))            {                linker[v]=u;                return true;            }        }    return false;}int hungary(){    int res=0;    int u;    memset(linker,-1,sizeof(linker));    for(u=0;u<uN;u++)    {        memset(used,0,sizeof(used));        if(dfs(u))  res++;    }    return res;}/**匈牙利算法板子**/bool pan(int x) {    for(int i=2;i*i<=x;i++) {        if(x%i==0) {            return 0;        }    }    return 1;}int sov(void) {    int cnt=0;    for(int i=y;i<=z;i++) {        if(pan(i)) {            cnt++;            if(cnt==2) return 0;        }    }    uN=x;vN=x;    for(int i=y;i<=z;i++)        for(int j=1;j<=x;j++) {            if(i%j==0) {                g[i-y][j-1]=1;            }        }    int res=hungary();    return res==x;}int main(){    int t;    int n,s;    int kase=0;    scanf("%d",&t);    while(t--) {        memset(g,0,sizeof g);        scanf("%d%d",&n,&s);        x=min(n,s);        y=max(n+1,s+1);        z=y+x-1;        int ans=sov();        if(ans!=0) printf("Case #%d: Yes\n",++kase);        else printf("Case #%d: No\n",++kase);    }    return 0;}
0 0