首先如果s+1~s+n中有两个数是素数,那么肯定是no;也就是如果1~2e9中素数的最大距离如果是m,那当n>m时就不成立了。(其实上这有一点问题)
我直接假设m=1000,事实上m比500还要小。
那么现在问题就降为
1≤T≤100.
1≤n≤1000.
0≤s≤1e9.
那么问题就很简单了,如果s+k是某个i的倍数,那么s+k就是可能和i进行匹配(1可以和任何一个数匹配)。然后找最大匹配数是否==n-1(由于1可以和任何一个数匹配,所以把它移掉,减少边数) (二分图匹配!!!)
当时wa了,wa了。
怎么看都没敲错啊!队友说看题,突然哦,你取s=0,n=100000。纳尼,居然跑出来是no。特判呗
wa
队友:s=1也是可以的,我:特判
队友:等等,3呢 我: 哦。。。。。。
这样考虑 s+1<=n时,s+1~s+n与1~n有交叉,显然交叉的部分直接匹配就可以,那就剩n+1~s+n和1~s匹配。其实现在就相当于n和s的值换了一下。(所以此时n>500就应该改为(n>500&&s+1>n)||(s>500&&s+1<=n))
ac!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <stack>
#include <vector>
#include <cstring>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=505;
const int inf=0x3f3f3f3f;
vector<int> G[MAXN];
int Mx[MAXN],My[MAXN];
int dx[MAXN],dy[MAXN];
int dis,n;
bool used[MAXN];
bool SearchP(void)
{
queue<int > Q;
dis=inf;
msc(dx);
msc(dy);
for(int i=2;i<=n;i++)
if(Mx[i]==-1){
Q.push(i);
dx[i]=0;
}
while(!Q.empty()){
int u=Q.front();
Q.pop();
if(dx[u]>dis) break;
int sz=G[u].size();
for(int i=0;i<sz;i++)
{
int v=G[u][i];
if(dy[v]==-1){
dy[v]=dx[u]+1;
if(My[v]==-1) dis=dy[v];
else{
dx[My[v]]=dy[v]+1;
Q.push(My[v]);
}
}
}
}
return dis!=inf;
}
bool DFS(int u)
{
int sz=G[u].size();
for(int i=0;i<sz;i++)
{
int v=G[u][i];
if(!used[v]&&dy[v]==dx[u]+1){
used[v]=true;
if(My[v]!=-1&&dy[v]==dis) continue;
if(My[v]==-1||DFS(My[v])){
My[v]=u;
Mx[u]=v;
return true;
}
}
}
return false;
}
int MaxMatch(void)
{
int res=0;
msc(Mx);
msc(My);
while(SearchP()){
ms(used);
for(int i=2;i<=n;i++)
if(Mx[i]==-1&&DFS(i))
res++;
}
return res;
}
int main(int argc, char const *argv[])
{
int t,ti=0;
scanf("%d",&t);
while(++ti<=t){
int s;
scanf("%d%d",&n,&s);
printf("Case #%d: ",ti );
if(s<=2) {puts("Yes");continue;}
if((n>500&&s+1>n)||(s>500&&s+1<=n)) {puts("No");continue;}
if(n>500) swap(n,s);
for(int i=2;i<=n;i++)
{
G[i].clear();
for(int j=s+1;j<=s+n;j++)
if(j%i==0) G[i].push_back(j-s);
}
puts(MaxMatch()==n-1?"Yes":"No");
}
return 0;
}