A. Hilbert's Hotel(數學)


傳送門

\(看了一下網上都沒什么題解,自己寫一篇吧,對你有幫助的話留個言吧~\)

\(\color{Orange}{----------------------分割------------------------}\)

\(\color{Green}{一、分析問題}\)

\(對於給定的n和數組a,其實是有循環存在的\)

\(比如[0,n)模n后余數必定是[0,n)\)

\([n,2n)模n后余數必定是[0,n)\)

\(現在我們的目的是判斷是否所有數都是互不相等的。\)

\(\color{Orange}{二、舉例子發現規律}\)

\(拿這組樣例來說\)

\(4\)
\(5\ 5\ 5\ 1\)

\(按照我們上面的循環節,把操作后得到的數寫出來\)

\([0,3]:5\ 6\ 7\ 4\)
\([4,7]:9\ 10\ 11\ 8\)
\(.............\)

\(可以發現,[4,7]就是由[0,3]都加n得來的,這很容易理解\)

\(那么我們可以把所有循環節看成由[0,3]加上nk得來的\)

\(所以現在的問題是已知集合={5+nk,6+nk,7+nk,4+nk},求是否有相同的數字\)

\(因為要互不相同,所以5、6、7、4模n后應該互不相等\)

\(\color{Red}{為什么?因為如果模n后相等,就一定存在某個k使得x_1=x_2+kn}\)

\(\color{Purple}{三、算法實現}\)

\(問題到這里應該就很簡單了\)

\(先處理出[0,n)操作后得到的數字(也就是先處理一個循環節)\)

\(然后對處理后的每個數對n求余,如果余數互不相等說明不存在重復的數字\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+9;
int n,t;
int a[maxn],b[maxn];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		for(int i=0;i<n;i++)
			b[i]=i+a[i%n];//處理第一個循環節 
		for(int i=0;i<n;i++)	b[i]=(b[i]%n+n)%n;//對n取余 
		sort(b,b+n);//排序后,如果余數互不相等,必定是0,1,2...n-1 
		int flag=1;
		for(int i=0;i<n;i++)
		if(b[i]!=i)	flag=0;
		if(flag)	cout<<"YES";
		else	cout<<"NO";
		cout<<endl;
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM