HDU 5943 Kingdom of Obsession

题意:n个人编号为[s+1, s+n],有n个座位编号为[1,n],编号为 i 的人只能坐到编号为它的约数的座位,问每个人是否都有位置坐。

题解:由于质数只能坐到1或者它本身的位置上,所以如果[n+1,n+s]区间内如果有多于一个质数时肯定无解,
有解时s 一定很小因为1e9以内,最远的两个素数相差282 (打表得出),
可以证明 [s+1,n]这一段数肯定坐到自己编号的位置上要更好
所以剩下的用匈牙利匹配一下即可

简单证明一下“ [s+1,n]这一段数肯定坐到自己编号的位置上要更好”

如果有更好的位置,设x为[s+1,n]内的一个数,y为大于n的一个数

且不存在比s小的数a 是得y%a=0

但是 x%a=0 且 y%x=0

这样显然矛盾

代码:

const int maxn = 1000;

int n, s;

vector<int> G[maxn];
bool vis[maxn];
int match[maxn];
bool dfs(int u) 
{
    for (int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i];
        if (vis[v]) continue;
        vis[v] = true;
        if (match[v] == -1 || dfs(match[v])) 
        {
            match[v] = u;
            return true;
        }
    }
    return false;
}

int hungary(int n) //传入二分图一边的节点数
{
    int matches = 0;
    memset(match, -1, sizeof match);
    for(int i = 1; i <= n; ++i) 
    {
        memset(vis, 0, sizeof vis);
        matches += dfs(i);
    }
    return matches;
}

void init()
{
    for (int i = 1; i < maxn; i++) G[i].clear();
    scanf("%d%d", &n, &s);
}


void solve()
{
    if (s > 600 && n > 600) 
    {
        printf("No
");
        return;
    }
    if (n <= 600) 
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if ((s + i) % j == 0)
                {
                    G[i].push_back(j);
                }
            }
        }
        int m = hungary(n);
        if (m == n) printf("Yes
");
        else printf("No
");
        return;
    }
    for (int i = 1; i <= s; i++)
    {
        for (int j = 1; j <= s; j++)
        {
            if ((n + i) % j == 0)
            {
                G[i].push_back(j);
            }
        }
    }
    int m = hungary(s);
    if (m == s) printf("Yes
");
    else printf("No
");
}

int main()
{
    int T, kase = 0;
    scanf("%d", &T);
    while (T--)
    {
        printf("Case #%d: ", ++kase);
        init();
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liangyongrui/p/6012114.html