题目链接
https://vjudge.net/problem/ZOJ-4101
题解思路
赛场想的是 O ( n l o g n ) O(nlogn) O(nlogn)的算法,T了有20发
从头讲一下,就是化简一下 Δ \Delta Δ x x x和 Δ \Delta Δ y y y 这里我设的是变化前减去变化后,我们可以把数组看做是初始的,给定的x和y是变化后的。
化简完:
Δ
\Delta
Δ
x
=
(
j
−
i
)
∗
(
a
i
−
a
j
)
x=(j-i)*(a_i-a_j)
x=(j−i)∗(ai−aj)
Δ
\Delta
Δ
y
=
(
j
−
i
)
∗
(
a
i
+
a
j
)
∗
(
a
i
−
a
j
)
y=(j-i)*(a_i+a_j)*(a_i-a_j)
y=(j−i)∗(ai+aj)∗(ai−aj)
相除得到 a i + a j a_i+a_j ai+aj的 s u m sum sum,如果不整除输出0
然后 O ( n ) O(n) O(n)枚举 i i i, a j aj aj= s u m − a i sum-a_i sum−ai,然后代入 Δ \Delta Δ x x x的式子中验证是否满足 a j = a j aj=a_j aj=aj
时间复杂度: O ( n ) O(n) O(n)
注意特判和限制条件
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define debug cout<<"fuck"<<endl;
#define pb push_back
#define endl '\n'
const int mod=(int)1e9+7;
const int maxn=(int)1e5+5;
int n;
int a[maxn];
int x,y;
int xx,yy;
int delx,dely;
int cnt[maxn];
signed main()
{
IOS
int t;
cin>>t;
while(t--)
{
memset(cnt,0,sizeof(cnt));
xx=0,yy=0;
cin>>n>>x>>y;//原始的
for(int i=1;i<=n;i++)
{
cin>>a[i];
cnt[a[i]]++;
xx+=i*a[i];//交换一次后的
yy+=i*a[i]*a[i];
}
delx=x-xx;
dely=y-yy;
//cout<<delx<<' '<<dely<<endl;
if(delx==0&&dely==0)//相同值交换
{
//debug;
int ans=0;
for(int i=1;i<=1e5;i++)
{
if(cnt[i]>=2)
{
ans+=cnt[i]*(cnt[i]-1)/2;
}
}
cout<<ans<<endl;
continue;
}
else if(delx==0||dely==0||dely%delx!=0)
{
//debug
cout<<0<<endl;
continue;
}
int sum=dely/delx;//ai+aj
//cout<<sum<<endl;
int res=0;
for(int i=1;i<=n;i++)
{
int aj=sum-a[i];
if(aj<1||(aj-a[i]==0)||(delx%(aj-a[i]))!=0)
{
continue;
}
int j=delx/(a[i]-aj)+i;
if(j>n||j<1)continue;
//cout<<i<<' '<<aj<<' '<<j<<endl;
if(aj==a[j])res++;
}
cout<<res/2<<endl;
}
return 0;
}