2019浙江省赛B zoj4101 Element Swapping(推公式)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6003

题意

(数组a通过交换一对数字,得到了b数组,给出x=sum^n_{k=1}ka_k和y=sum^n_{k=1}ka_k^2和b数组,问有多少对l,r(l<=r)能满足条件)

题解

  • (frac{Y_2-Y_1}{X_2-X_1}=a_i+a_j=b_i+b_j)
  • (X_2-X_1 = (a_i-a_j)*(j-i)=(b_j-b_i)*(j-i))
  • (第一个式子左边为一个定值,所以b_i和b_j一一对应,可以枚举b数组)
  • (第二个数组可以化为frac{X_2-X_1+(b_j-b_i)i}{b_j-b_i} = j,假设j>i(方便计数),枚举b_i通过式子一可以计算b_j,然后通过式子二可以计算出j,判一下b_j是否等于j)
  • (X_2-X_1=0,Y_2-Y_1 eq0,则不合法)
  • (X_2-X_1=0,Y_2-Y_1=0推出a_i=a_j,j eq i)
  • (Y_2和X_2是由b数组计算而得的,而X_1和Y_1是题目提供的,所以存在(X_2-X_1) mid (Y_2-Y_1))
#include<bits/stdc++.h>
#define ll long long 
#define Map map<ll,ll>::iterator
#define MAXN 100005
#define se second
using namespace std;
map<ll,ll>cnt;
ll X1,Y1,X2,Y2,a[MAXN];
int T,n;
int main(){
    cin>>T;
    while(T--){
        cnt.clear();
        scanf("%d%lld%lld",&n,&X1,&Y1);
        X2=Y2=0;
        for(ll i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            cnt[a[i]]++;
            X2+=a[i]*i;Y2+=a[i]*a[i]*i;
        }
        ll dx=X2-X1,dy=Y2-Y1;
        if(dx==0){
            if(dy!=0){
                puts("0");continue;
            }
            ll ans=0;
            for(Map it=cnt.begin();it!=cnt.end();it++){
                ans+=((it->se)-1)*(it->se)/2;
            }
            printf("%lld
",ans);
            continue;
        }
        if(dy%dx){
            puts("0");continue;
        }
        //cout<<dx<<" "<<dy<<endl;
        ll dt=dy/dx,ans=0;
        //cout<<dt<<endl;
        for(ll i=1;i<=n;i++){
            ll Aj=dt-a[i];
            if((Aj-a[i])==0)continue;
            ll j=(dx+(Aj-a[i])*i)/(Aj-a[i]);
            if(j<=i||j>n)continue;
            if(a[j]==Aj)ans++;
        }
        printf("%lld
",ans);
    }
}
原文地址:https://www.cnblogs.com/VIrtu0s0/p/10784476.html