一天,jyb 去视察他的军队。军队中的每名士兵都有一个编号,从1 开始编号,现在jyb 从抽出了一些编号连续的士兵,想让它们排成1 列,排队的规则是这样的:对于第i 名士兵,他的编号必须是i 的倍数。现在jyb 想知道是否能成功排队
Input
第1 行,1 个整数T, 表示数据组数,对于每组数据:
第1 行,2 个整数n; s,n 表示选中的士兵数,编号是s + 1; s + 2; s + 3; ……; s + n
Output
对于每组数据,如果能成功排队,输出Yes;不能,输出No。
in:
2
5 14
4 11
out:
No
Yes
第一眼感觉是二分图,然后瞎打了个二分图匹配的暴力上去
#include<bits/stdc++.h>
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
int T,n,s,cnt;
int can[405][405];
bool vis[405];
int match[405];
inline void swap(int &a,int &b){int t=a;a=b;b=t;}
bool check(int x)
{
if(!x) return false;
for(register int i=1;i<=n;++i)
{
if(!vis[i]&&can[i][x])//未访问且可匹配
{
vis[i]=1;
if(!match[i]||check(match[i]))//若没有匹配或下一个有匹配
{
match[i]=x;
return true;
}
}
}
return false;
}
template<class T> inline void read(T &re)
{
re=0;T sign=1;char tmp;
while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;re=tmp-'0';
while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=re*10+(tmp-'0');re*=sign;
}
inline void clear()
{
mem(can);
mem(match);
cnt=0;
}
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
read(T);
while(T--)
{
clear();
read(n);read(s);
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
if(!((s+i)%j)) can[i][j]=1;
for(register int i=1;i<=n;++i)
{
mem(vis);
if(check(i)) ++cnt;
}
printf(n==cnt?"Yes\n":"No\n");
}
return 0;
}
T到飞起
这是因为二分图的复杂度是O(n³),1e9的数据显然过不去,想到使用网络流
抱歉网络流也过不去,告辞
转念一想,1e9范围内,相邻质数的差不超过600
那么超过600就一定会有两个质数同时要求匹配,质数的因子只有1和本身,因此一定不匹配
if(n>600) {printf("No\n");continue;}
另外,如果n>s呢?画画图,等价于swap(n,s)
这样便达到了缩小n的目的
于是把暴力代码改改
#include<bits/stdc++.h>
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
int T,n,s,cnt;
int can[405][405];
bool vis[405];
int match[405];
inline void swap(int &a,int &b){int t=a;a=b;b=t;}
bool check(int x)
{
if(!x) return false;
for(register int i=1;i<=n;++i)
{
if(!vis[i]&&can[i][x])//未访问且可匹配
{
vis[i]=1;
if(!match[i]||check(match[i]))//若没有匹配或下一个有匹配
{
match[i]=x;
return true;
}
}
}
return false;
}
template<class T> inline void read(T &re)
{
re=0;T sign=1;char tmp;
while((tmp=getchar())&&(tmp<'0'||tmp>'9')) if(tmp=='-') sign=-1;re=tmp-'0';
while((tmp=getchar())&&(tmp>='0'&&tmp<='9')) re=re*10+(tmp-'0');re*=sign;
}
inline void clear()
{
mem(can);
mem(match);
cnt=0;
}
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
read(T);
while(T--)
{
clear();
read(n);read(s);
if(n>s) swap(n,s);
if(n>400) {printf("No\n");continue;}
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
if(!((s+i)%j)) can[i][j]=1;
for(register int i=1;i<=n;++i)
{
mem(vis);
if(check(i)) ++cnt;
}
printf(n==cnt?"Yes\n":"No\n");
}
return 0;
}
/*
2
5 14
4 11
*/
就可以了
(当然我考试的时候写的400上界,对拍了一下没什么问题= =,600那个数据太特殊了,而且二分图跑不过去qwq)