Element Swapping
链接
[http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6003]
题意
给你n,x,y;
x=a11+a22+...+a[i]i+...+a[j]j+...+n*a[n];
y=a1a11+a2a22+...+a[i]a[i]i+...+a[j]a[j]j+...+a[n]a[n]n;
再给你一个交换一次某两个位置后的a数组
让你找有多少交换的可能
分析
x=a1*1+a2*2+...+a[i]*i+...+a[j]*j+...+n*a[n];
x1=a1*1+a2*2+...+a[j]*i+...+a[i]*j+...+n*a[n];
x-x1=i*(a[i]-a[j])+j*(a[j]-a[i])
x-x1=(i-j)*(a[i]-a[j]);
y=a1*a1*1+a2*a2*2+...+a[i]*a[i]*i+...+a[j]*a[j]*j+...+a[n]*a[n]*n;
y1=a1*a1*1+a2*a2*2+...+a[j]*a[j]*i+...+a[i]*a[i]*j+...+a[n]*a[n]*n;
y-y1=(i-j)*(a[i]*a[i]-a[j]*a[j])=(i-j)*(a[i]-a[j])*(a[i]+a[j]);
如果x-x1==0&&y-y1!=0是不可能交换的
如果x-x1==0&&y-y1==0就只可以交换相等数字,此时用map统计每个数字的个数
a[i]+a[j]=y-y1/x-x1;
j=(x-x1)/(a[i]+a[j])+i;
而a[j]= y-y1/x-x1 - a[i];
带到上面就求出j,然后就检验a[j]是否满足
x-x1=i*(a[i]-a[j])+j*(a[j]-a[i])
y-y1=(i-j)*(a[i]*a[i]-a[j]*a[j])=(i-j)*(a[i]-a[j])*(a[i]+a[j]);
满足就sum++;
这种东西以前确实没有会,现在知道他的套路了
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
map<ll,ll> mp;
int main(){
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t,n;
ll x,y;
cin>>t;
while(t--){
cin>>n>>x>>y;
ll x1=0,y1=0;
mp.clear();
for(int i=1;i<=n;i++){
cin>>a[i];
x1+=1ll*a[i]*i;
y1+=1ll*a[i]*a[i]*i;
mp[a[i]]++;
}
//cout<<x1<<' '<<y1<<endl;
if(x1==x){
if(y1!=y){
cout<<0<<endl;
}
else{
ll sum=0;
for(map<ll,ll>::iterator it=mp.begin();it!=mp.end();it++){
ll cur=it->second;
sum+=cur*(cur-1)/2;
}
cout<<sum<<endl;
}
}
else{
if(abs(y-y1)%abs(x-x1)){
cout<<0<<endl;
continue;
}
ll sum=0,ty=y-y1,tx=x-x1;
ll tem=ty/tx;
//tem=ai+aj
for(int i=1;i<=n;i++){
ll aj=tem-a[i]; ll tj=a[i]-aj;
if(tj==0) continue;
if(abs(tx)%tj) continue;
int j=tx/tj+i;
if(j<=i||j>n) continue;
if(a[j]==aj&&(tx==(j-i)*(a[i]-aj))&&(ty==(j-i)*(a[i]*a[i]-a[j]*a[j])))
sum++;
}
cout<<sum<<endl;
}
}
return 0;
}