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

浙公网安备 33010602011771号