VIrtuoso

两把多兰剑加个布甲鞋

导航

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\neq0,则不合法\)
  • \(X_2-X_1=0,Y_2-Y_1=0推出a_i=a_j,j\neq i\)
  • \(Y_2和X_2是由b数组计算而得的,而X_1和Y_1是题目提供的,所以存在(X_2-X_1)\nmid (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\n",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\n",ans);
    }
}

posted on 2019-04-28 15:58  VIrtuoso  阅读(770)  评论(1编辑  收藏  举报