首页 > 其他分享 >Yet Another mod M

Yet Another mod M

时间:2022-10-25 15:46:32浏览次数:101  
标签:maxx return 5005 int id Another ans Yet mod

传送门

看到 \(N\) 这么小,容易想到枚举下标 \(i\) ,设 \(C[j]=|A[i]-A[j]|\),只要 \(M|C[j]\),那么 \(A[i]=A[j]\mod M\)。

同时因为若 \(p|M\),那么可以以 \(p\) 为答案。

所以可以对每个 \(C[j]\) 分解质因数,用 \(map\) 记录有多少个 \(C[j]\) 有某个质因子。

时间复杂度 \(O(N^2\sqrt{N}\log N)\) 显然会 T。

于是注意到我们只需要找到一种方案,而且从方案中任意一个数开始都可以求出具体方案,而且方案中元素个数很多(\(\frac{N}{2}\))那么就采用随机化算法,每次有 \(\frac{1}{2}\) 的概率成功,跑个 5、6 次绰绰有余。

(但说实话,若是 OI 中遇到这种题,没人敢写随机吧。。。

Notice:可以让随机次数随着 \(N\) 动态改变 ,比如设 \(T=\frac{100000}{N}\),这样充分利用时限

(注意!!! \(M!=2\),所以得让 \(4\) 充当质数,细节还是挺多的。。。)

#include<bits/stdc++.h>
using namespace std;
int a[5005],c[5005];
map<int, int> h;
int n;
inline int work(){
	for(int i=2;i<=n;++i)c[i]=abs(a[i]-a[1]);
	int maxx=0,id=-1;
	h.clear();
	for(int i=2;i<=n;++i){
		int x=c[i];
		for(int j=3;j*j<=c[i];++j){
			if(x%j==0){
				if(j>2){
					h[j]++;
					if(h[j]>maxx)maxx=h[j],id=j;
				}
				while(x%j==0)x/=j;
				if(x==1)break;
			}
		}
		if(x>2){
			if(x%4!=0&&x%2==0)x/=2;
			h[x]++;
			if(h[x]>maxx)maxx=h[x],id=x;
		}
	}
	if(maxx+1>n-maxx-1)return id;
	else return -1;
}
int main(){
	srand((unsigned)time(0));
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	
	int ans=-1;
	int T=100000/3/n;
	while(T--){
		int x=1ll*rand()*rand()%n+1;
		
		swap(a[x],a[1]);
		ans=max(ans,work());
		if(ans>0)break;
	}
	
	cout<<ans<<endl;
	return 0;
}

实际上,求质因子(遍历 \(\sqrt N\)) 和求所有约数(也是 \(\sqrt N\) 级别的)时间上差别不是很大,但求约数好写很多,所以若是无法线性筛预处理,直接求约数更方便。

#include<bits/stdc++.h>
using namespace std;
int a[5005],c[5005];
map<int, int> h;
int n;
inline int work(){
	for(int i=2;i<=n;++i)c[i]=abs(a[i]-a[1]);
	int maxx=0,id=-1;
	h.clear();
	for(int i=2;i<=n;++i){
		int x=c[i];
		for(int j=1;j*j<=c[i];++j){
			if(x%j==0){
				if(j>2){
					h[j]++;
					if(h[j]>maxx)maxx=h[j],id=j;
				}
				if(c[i]/j>2&&j*j!=c[i]){
					h[c[i]/j]++;
					if(h[c[i]/j]>maxx)maxx=h[c[i]/j],id=c[i]/j;
				}
			}
		}
	}
	if(maxx+1>n-maxx-1)return id;
	else return -1;
}
int main(){
	srand((unsigned)time(0));
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	
	int ans=-1;
	int T=50000/3/n;
	while(T--){
		int x=1ll*rand()*rand()%n+1;
		
		swap(a[x],a[1]);
		ans=max(ans,work());
		if(ans>0)break;
	}
	
	cout<<ans<<endl;
	return 0;
}

标签:maxx,return,5005,int,id,Another,ans,Yet,mod
From: https://www.cnblogs.com/Huster-ZHY/p/16825036.html

相关文章