HDU-5943 Kingdom of Obsession(数学+二分图匹配)

Kingdom of Obsession

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1202    Accepted Submission(s): 368


Problem Description
There is a kindom of obsession, so people in this kingdom do things very strictly.

They name themselves in integer, and there are n people with their id continuous (s+1,s+2,,s+n) standing in a line in arbitrary order, be more obsessively, people with id x wants to stand at yth position which satisfy

xmody=0


Is there any way to satisfy everyone's requirement?
 

Input
First line contains an integer T , which indicates the number of test cases.

Every test case contains one line with two integers n , s .

Limits
1T100 .
1n109 .
0s109 .
 

Output
For every test case, you should output 'Case #x: y', where x indicates the case number and counts from 1 and y is the result string.

If there is any way to satisfy everyone's requirement, y equals 'Yes', otherwise y equals 'No'.
 

Sample Input
  
  
2 5 14 4 11
 

Sample Output
  
  
Case #1: No Case #2: Yes

题解:数学+二分图匹配

打表可知:n和s存在对称关系,即n和s互换对答案没有影响
根据这一点,可以使n小于s。这样有什么用呢?


我们知道素数的约数只有1和本身,我们令n<s后,编号的区间为[s+1,s+n]

因此只要再区间[s+1,s+n]中有2个素数,那么这种情况肯定是No(因为[1,n]中只有一是这些素数的约数)

再根据10E以内相邻素数之差不会超过300,因此只要n>300即输出No

当n在300以内时,就可以用二分图匹配将编号和其约数配对,如果匹配成功则输出Yes

#include<bits/stdc++.h>
using namespace std;
const int MX = 2e3 + 5;
struct Edge{
    int v,nxt;
}E[MX*MX];
int head[MX],tot;
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
void add(int u,int v){
    E[tot].v=v;
    E[tot].nxt=head[u];
    head[u]=tot++;
}
int match[MX];
bool vis[MX];
bool DFS(int u) {
    for(int i = head[u]; ~i; i = E[i].nxt) {
        int v = E[i].v;
        if(!vis[v]) {
            vis[v] = 1;
            if(match[v] == -1 || DFS(match[v])) {
                match[v] = u;
                return 1;
            }
        }
    }
    return 0;
}
int BM(int n) {
    int res = 0;
    memset(match, -1, sizeof(match));
    for(int u = 1; u <= n; u++) {
        memset(vis, 0, sizeof(vis));
        if(DFS(u)) res++;
    }
    return res;
}
int main(){
    int T,n,s;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        printf("Case #%d: ",cas);
        scanf("%d%d",&n,&s);
        if(n>s) swap(n,s);
        if(n>600) {
            printf("No\n");
            continue;
        }
        init();
        for(int i=s+1;i<=s+n;i++){
            for(int j=1;j<=n;j++){
                if(i%j==0) {
                    add(i-s+n,j);
                    add(j,i-s+n);
                }
            }
        }
        if(BM(2*n)==2*n) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值