hdu5943——数论知识+二分图匹配
Posted hans774882968
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu5943——数论知识+二分图匹配相关的知识,希望对你有一定的参考价值。
题意
输入n和s(均为1e9),问是否存在一个n的排列p,使得每个i=1~n,(s+i) % p[i] == 0。
思路
数论和二分图匹配居然能结合起来qwq
首先要意识到这实际上是求一个映射,然后要意识到这里有一个争抢性质:一个p[i]只能拥有一个s+i,且一个s+i只能被一个p[i]占领。那么就可以建模为二分图,本题就是在问是否存在一个完美匹配。但是n和s是1e9,真的思路就断了吗?
我们发现一个事情(太菜了发现不了啊QAQ):如果s≥n(从而区间无交)且{ s+i }里面有2个素数,那么它们都只能抢1,那么答案一定是false。那么在s大于n的前提下,我们希望知道1e9范围内最大的素数间距。这玩意大约可以打表?总之这个最大间距不超过1000。那么在s大于n的前提下,n大于1000就返回false。
接下来看s<n的情况:不妨让重叠部分匹配,然后考虑1~s 和 n+1~n+s匹配,即转化为一个n1=s0且s1=n0的子问题(注:在该子问题回答为false时是否还有其他方案使得原问题为true?),这个操作相当于参数交换。这样就转化为上面的情况。
综上,先交换使得s≥n,再跑一个1000点以内的匈牙利板子。
总结:这种范围大了,解已确定,范围不够大则套板的题,在ICPC/CCPC里面似乎有点常见?
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i = (a);i <= (b);++i)
#define re_(i,a,b) for(int i = (a);i < (b);++i)
#define dwn(i,a,b) for(int i = (a);i >= (b);--i)
const int SZ = 1000 + 5;
int n,s;
bool vis[SZ];int match[SZ];
vector<int> G[SZ];
template<typename Type>inline void read(Type &xx){
Type f = 1;char ch;xx = 0;
for(ch = getchar();ch < '0' || ch > '9';ch = getchar()) if(ch == '-') f = -1;
for(;ch >= '0' && ch <= '9';ch = getchar()) xx = xx * 10 + ch - '0';
xx *= f;
}
int dfs(int u){
for(int v: G[u]){
if(vis[v]) continue;
vis[v] = true;
if(!match[v] || dfs(match[v])){
match[v] = u;
return 1;
}
}
return 0;
}
int hungary(int n){
memset(match,0,sizeof match);
int ans = 0;
rep(i,1,n){
memset(vis,0,sizeof vis);
ans += dfs(i);
}
return ans;
}
int main(int argc, char** argv) {
int T,cas = 0;read(T);
while(T--){
read(n);read(s);
if(n > s) swap(n,s);
if(n > 1000){
printf("Case #%d: No\\n",++cas);continue;
}
rep(i,1,n) G[i].clear();
rep(i,1,n)
rep(j,s+1,s+n)
if(j % i == 0)
G[i].push_back(j-s);
printf("Case #%d: %s\\n",++cas,hungary(n) == n ? "Yes" : "No");
}
return 0;
}
以上是关于hdu5943——数论知识+二分图匹配的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5943 Kingdom of Obsession 二分图的匹配
HDU 5943 Kingdom of Obsession 二分图匹配 匈牙利算法 (中国大学生程序设计竞赛(杭州))
HDU5943 Kingdom of Obsession(思路题+二分匹配)