CodeForeces-Partitioning the Array

题目

所需知识

必须要明白一个知识:
如果a%p=b%p=c,(a-b)%p=c。
证明:


首先,由于a % p = c,说明a可以表示为a = kp + c(其中k是一个整数)。同样,由于b % p = c,说明b可以表示为b = mp + c(其中m是一个整数)。

现在,我们来计算(a - b)% p:

(a - b)% p = (kp + c - mp - c) % p
= (kp - mp) % p
= p(k - m) % p
= 0
证毕

题目思路

首先 一定要好好读题,题目说了划分结束后

if there exists some positive integer m得一分


并不是说这个划分条件下 找到一个m就得一分,n个m就n分,不可能啊

那不然 1 1 1 1 这种得多少分不得无穷了


所以一定要结合下面样例解释去读题,我之前老觉得这个样例解释少看,因为

它得解释并不是正解的做法,但是拿来验证答案是可以的。。。。。。


然后做法很简单的,求gcd,


我一开始理解成只要枚举因子,如果有相同的则得分,但是因子每两个数有很多个,这样太麻烦,直接用最大公因数可以直接涵盖了


比如 25 50 gcd是25 虽然5也是因子但是25可以包含它,所以用gcd进行更新才是正解,但是想到了因子这些其实也就知道这题一定要用gcd才行。


实现过程

要学习一个好的枚举因子的办法,就是如果i是因子 那n/i也是

可以把时间复杂度弄到sqrt(n)去,然后在do函数复杂度是logn*n。

然后对于1进行特判就行

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int a[200005];	int n;
int  Do(int x)
{
 int g=0;
	for(int i=1;i<=x;i++)
	{    
		for(int j=i+x;j<=n;j=j+x)
		{
			g=__gcd(g,abs(a[j]-a[i]));		
		}
	
	}	
	if(g==1)return 0;
	return 1;
//		v.push_back(x);
//	}
//	int cnt=v[0];
//	vector<int>::iterator it=v.begin()+1;
//    while(it!=v.end())
//	{
//		cnt=__gcd(cnt,*it);
//	}
//
//	if(cnt==1)return 0;
//	else return 1;
}
void solve()
{
	cin>>n;
	long long ans=0;
	
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i*i<=n;i++)
	{  
		if(i==1){
		 if(n!=1)
		 {
			 if(Do(i))
			 ans++;
		 }
	//	cout<<ans<<endl;	
	  ans++;
		}		
		else if(n%i==0)
		{ // cout<<i<<endl;
			if(Do(i))
			{ ans++;
		//	cout<<ans<<endl;
			}
			
			if(i!=n/i&&Do(n/i)){ans++;//cout<<ans<<endl;
			}
		}
	}
	cout<<ans<<endl;
}
int main()
{
	
  int t;
	cin>>t;
	while(t--)
		solve();
	
	
	return 0;
}

最后

今晚有div.3打,坐了一天的车子真的累,然后每天都是半夜很晚睡觉,熬夜这个习惯改不了,没事做也不想睡觉,好想今晚不打,但是宝贵的涨分机会太难得了。好吧 只好打了。今天礼拜一没更新估值好气,本来橙名的。

posted @ 2025-04-16 20:00  LteShuai  阅读(18)  评论(0)    收藏  举报