HDU 5943 Kingdom of Obsession 二分圖匹配+素數篩

  • Kingdom of Obsession
    • 這一題需要思維抽象能力,如果僅看到問題的表面(數論),則無從下手。
    • 問題的實質是將1, 2, 3, …, n這n個數(記爲y)與s+1, s+2, s+3, … s+n這n個數(記爲x)建立一一映射,並且每個映射都滿足x%y=0。
    • x%y=0可以寫成x=ky (k>0, k∈N),即x爲y的倍數。
    • 若s<n,則x與y有一部分相同,我們可以將相同的部分與自身映射,使sub=n-s, n-=sub, s+=sub(此操作等價於swap(s,n)),問題就被簡化爲x與y不重合的情況。
    • 既然x與y無交集部分,且x爲y的倍數,說明x集合中不可以同時有兩個素數(一個素數可以使其%1)。本地用歐拉篩篩出所有1e9內素數,統計出相鄰素數之間的最大間隔,可知相鄰素數之間間隔不會超過1000。
    • 所以,若n≥1000,則一定無解。
    • n<1000時,將x與y兩個集合看成二分圖,兩點之間存在邊的條件爲x%y=0。用匈牙利算法可以計算出二分圖的最大匹配數。若最大匹配數≠n,則無解,否則有解。

代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool g[1010][1010];
int linker[1010],uN,vN;
bool used[1010];
bool dfs(int u)
{
	for(int v=0;v<vN;++v)
	{
		if(g[u][v]&&!used[v])
		{
			used[v]=true;
			if(linker[v]==-1||dfs(linker[v]))
			{
				linker[v]=u;
				return true;
			}
		}
	}
	return false;
}
int hungary()
{
	int res=0;
	memset(linker,-1,sizeof(linker));
	for(int u=0;u<uN;++u)
	{
		memset(used,false,sizeof(used));
		if(dfs(u))
		{
			++res;
		}
	}
	return res;
}
int main()
{
	int T,kcase=0;
	scanf("%d",&T);
	while(T--)
	{
		int n,s;
		scanf("%d%d",&n,&s);
		if(n>s)
		{
			swap(n,s);
		}
		if(n>1000)
		{
			printf("Case #%d: No\n",++kcase);
			continue;
		}
		memset(g,false,sizeof(g));
		uN=vN=n;
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=n;++j)
			{
				if(!((s+j)%i))
				{
					g[j-1][i-1]=true;
				}
			}
		}
		if(hungary()==n)
		{
			printf("Case #%d: Yes\n",++kcase);
		}
		else
		{
			printf("Case #%d: No\n",++kcase);
		}
	}
	return 0;
}
發佈了24 篇原創文章 · 獲贊 0 · 訪問量 776
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章