original link - http://acm.hdu.edu.cn/showproblem.php?pid=5943
题意:
一个区间X:[s+1,s+n],将每个数对应到另外一个区间Y:[1,n],每个数只能被对应一次,x可以对应y当且仅当x%y=0。求是否可行。
解析:
如果区间有重叠,那么先将重叠部分匹配掉(x匹配x最优,因为2x可以匹配更多)
那么剩下不重叠部分,如果X有两个素数,那么一定不行。而没有两个素数的情况下,X的剩下部分不会超过250(素数距离),直接二分图匹配即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=605;
int line[N][N],boy[N],used[N];
int n,m;
int Find(int x)
{
int i,j;
for(i=1;i<=m;i++)
{
if(line[x][i]==1&&used[i]==0) //如果男生x与女生i有联系并且这个女生没有被当前这一轮的男生找过,就找这个女生
{
used[i]=1;
if(boy[i]==0||Find(boy[i])) //如果这个女生没有被别的男生找过或者找这个女生的男生还能找到别的女生,更新
{
boy[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
int n,s;
scanf("%d%d",&n,&s);
if(s>600&&n>600)
{
printf("Case #%d: No\n",++cas);
continue;
}
if(s<=1)
{
printf("Case #%d: Yes\n",++cas);
continue;
}
memset(line,0,sizeof(line));
memset(boy,0,sizeof(boy));
int sta=max(n+1,s+1),fin=n+s;
m=fin-sta+1;
for(int i=sta;i<=fin;i++)
{
for(int j=1;j<=m;j++)
if(i%j==0)
line[i-sta+1][j]=1;
}
int ans=0;
for(int i=1;i<=m;i++)
{
memset(used,0,sizeof(used));
ans+=Find(i);
}
printf("Case #%d: %s\n",++cas,ans==m?"Yes":"No");
}
return 0;
}