题目链接→戳
s,n 1e9的范围直接暴力匹配二分图肯定会T。。。
对于区间[1,n]和[s+1,s+n],如果存在重叠部分,
比如1,2,3......,n-2, n-1 , n
↓ ↓ ↓
s+1,s+2,s+3......s+n
s+1,s+2,s+2直接放在s+1,s+2,s+3的位置,只需要去匹配[1,s]和[n,s+n]
这样,我们需要去匹配的区间内就没有s+i可以放在s+i位置的了,如果区间内存在>=2个素数,这些素数只能放在第一个位置,这种情况肯定是No
对于2e9内的数据,打个表可以发现,两个素数间的最大距离为220?还是多少来着,也就是说,如果需要匹配的区间范围超过>440(这里用的450,没啥区别感觉)
的情况肯定也是No,这样我们进行二分图匹配的最大区间范围就缩小到了450,然后就直接用匈牙利算法去进行二分图匹配 get√
边的话……就暴力,可以整除就加边,嗯。
顺便补一补二分图匹配的相关知识,戳这些→二分图的最大匹配、完美匹配和匈牙利算法
好多博客写的都很棒啊,这里码几篇 二分图匹配(这里有匈牙利和km)
万能度娘 二分图及匹配算法
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAX=450; //<--匈牙利--> 二分图匹配 int t,n,s,cas=1; vector<int>e[MAX]; map<int,int>match; //存储求解结果 map<int,int>check; bool dfs(int u) { for(auto v:e[u]) { if(!check[v]) { check[v]=1; if(!match[v]||dfs(match[v])) { match[v]=u; return 1; } } } return 0; } int hungarian() { int ans=0; match.clear(); for(int u=1;u<=n;u++) { if(!match[u]) { check.clear(); if(dfs(u)) ans++; } } return ans; } int main() { cin>>t; while(t--) { for(int i=0;i<MAX;i++) e[i].clear(); cin>>n>>s; if(s<n)swap(n,s); //若s<n,[s+1,n]放在原位,二分匹配[n+1,s+n]与[1,s] if(n>MAX){ cout<<"Case #"<<cas++<<": No"<<endl; continue; } for(int i=1;i<=n;i++) { int temp=i+s; for(int j=1;j<=n;j++) if(temp%j==0) { e[j].push_back(temp); } } if(hungarian()==n) cout<<"Case #"<<cas++<<": Yes"<<endl; else cout<<"Case #"<<cas++<<": No"<<endl; } return 0; }