VOj - Kingdom of Obsession (数学优化+二分图匹配)

Kingdom of Obsession

题目链接: Kingdom of Obsession HDU - 2853

题意

给你一个起点s,和n要求从s+1到s+n的自然数按照一定次序排序,满足自己的值一定能整除自己的排序号


思路

题3目中的s和n都很大,所以暴力运算并不可取,那么我们就需要自己优化。题目显然一个素数在1以外找不到自己的座位,那么就可以从素数入手,数学原理可得。在1到1e9范围内任何两个素数之差,一定不会超过500,所以这个n一定不会超过五百,超过直接输出NO即可,在500的数据量下我们就可以用二分图匹配了,注意这里有一个陷阱,在一种情况下n可以为非常大的数,也会符合条件,就是1到n与s到s+n的区间有大量数字重叠的情况下,我们只需特判,就将重叠的地方删去,用一个 if (n > s) swap(n,s); 即可


代码

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(ll i = (ll)j;i <= (ll)k;i ++)
#define per(i,j,k) for(ll i = (ll)j;i >= (ll)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const ll MAXN = (ll)1e3+7;
const ll INF = (ll)0x3f3f3f3f;

ll K,N,M;
vector<ll> E[MAXN];
ll used[MAXN],nxt[MAXN];//在男生的某次访问里,女生能不能匹配到 //如果匹配到的话,这个男生是谁

bool Find(ll x){
    rep(i,0,E[x].size()-1){
        ll v = E[x][i];
        if (!used[v]){
            used[v] = 1;
            if (!nxt[v] || Find(nxt[v])){ //如果这个女生没有匹配到人,或者她匹配的男生可以腾位置的
                nxt[v] = x;
                return true;
            }
        }
    }
    return false;
}

ll match(){
    ll sum = 0;
    rep(i,1,N){
        mmm(used,0);
        if (Find(i)) sum ++;
    }
    return sum;
}

void init(){
    rep(i,1,N) E[i].clear();
    mmm(nxt,0);
}

int main()
{
    ll T;
    scanf("%lld",&T);
    rep(ca,1,T) {
        ll flag = 0;
        ll n,s;
        scanf("%lld %lld",&n,&s);
        if (n > s) swap(n,s);
        if (n >= 1000) flag = 1;
        else {
            N = n;
            init();
            rep(i,1,n) {
                rep(j,1,n) {
                    if ((i+s)%j == 0) E[i].pb(j);
                }
            }
            if (match() != n) flag = 1;
        }
        printf("Case #%lld: ",ca);
        if (flag) puts("No");
        else      puts("Yes");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值