K - Kingdom of Obsession 二分图+思维 CCPC
链接:https://vjudge.net/contest/364924#problem/K
题意:给出n跟s,让我们将(s+1,s+n)范围内的数找一个可能的次序让其满足每一个位置的数mod位置==0
即:val%pos==0
思路:首先我们可以想到的是二分图匹配解法,但是数据范围太大,操作不了
不过我们知道素数有个特性就是因数只有1和它本身。所以素数只能待在位置1或者标号为本身的位置上
1.如果m>n
在这种情况下,只要在(m+1,m+n)有一个素数,都是不可能匹配的。所以我们要算出两个素质之间的最大距离
如果n大于等于两个素数之间的距离,那么肯定是不可能匹配的。
如果小于直接二分图匹配一下。
2.如果m<=n
有一部分重合的地方,这部分的值跟位置相等,即满足mod==0的情况,这个时候就直接算后面的那部分即可(n,n+m)
在这种情况下,重合部分用掉的pos为(m,n),即剩下可用的pos为(1,m)所以可以直接用一个swap操作代替这一过程
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e4+10; 4 int vis[maxn]; 5 int n,s; 6 struct node 7 { 8 int v,nxt; 9 }G[maxn]; 10 int num;int head[maxn]; 11 int now[maxn]; 12 void add(int u,int v) 13 { 14 G[++num].v=v;G[num].nxt=head[u];head[u]=num; 15 } 16 int match(int u) 17 { 18 for(int i=head[u];i;i=G[i].nxt){ 19 int v=G[i].v; 20 if(!vis[v]){ 21 vis[v]=1; 22 if(!now[v]||match(now[v])){ 23 now[v]=u; 24 return 1; 25 } 26 } 27 } 28 return 0; 29 } 30 void init() 31 { 32 memset(head,0,sizeof(head)); 33 memset(now,0,sizeof(now)); 34 num=0; 35 } 36 int main() 37 { 38 int T; 39 scanf("%d",&T); 40 int Case=0; 41 while(T--){ 42 init(); 43 scanf("%d%d",&n,&s); 44 if(s<n) swap(s,n); 45 if(n>300){ 46 printf("Case #%d: No\n",++Case); 47 continue; 48 } 49 for(int i=1;i<=n;i++){ 50 for(int j=1;j<=n;j++){ 51 if((i+s)%j==0) add(i,j); 52 } 53 } 54 int ans=0; 55 for(int i=1;i<=n;i++){ 56 memset(vis,0,sizeof(vis)); 57 if(match(i)) ans++; 58 } 59 if(ans==n) printf("Case #%d: Yes\n",++Case); 60 else printf("Case #%d: No\n",++Case); 61 } 62 return 0; 63 }