2019浙江省程序设计竞赛 B:Element Swapping(数学 推公式)

版权声明:本文为博主原创文章,顺手点个赞叭~有问题欢迎指出(*╹▽╹*) https://blog.csdn.net/qq_41117236/article/details/89640765

【题面】

Element Swapping

【题解】

题意:给定一个长度为n的有两个元素被交换了位置的序列和x,y,x和y的含义如下图,输出可能被交换的元素对(i,j)的数目。

思路:一看就是数学题啊..

令原x,y为x1,y1,改变后x,y为x2,y2,交换元素为ai,aj(j>i),则得到以下公式

x2-x1=(j-i)*aj+(i-j)*ai =(i-j)(ai-aj)

y2-y1=(i-j)(ai^2-aj^2)

\frac{y2-y1}{x2-x1}=\frac{ai^2-aj^2}{ai-aj}=ai+aj

x2-x1=(i-j)*(ai-aj)->j=\frac{x2-x1}{aj-ai}+i

由公式可得,当x2-x1=0时,说明ai=aj,此时若y2-y1=0,则输出所有相等元素对数;若y2-y1≠0 ,则不合法。当x2-x1≠0时,由公式求出理论位置j和aj并判断是否相对应,若相对应则计数,最后输出答案即可。

【代码】

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
ll a[maxn];
map <ll,ll> mp;
map <ll,ll> ::iterator it;
int main()
{
    int t; scanf("%d",&t);
    while(t--){
        mp.clear();
        ll x1,y1,x2=0,y2=0; int n;
        scanf("%d%lld%lld",&n,&x1,&y1);
        for(ll i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            mp[a[i]]++;
            x2+=a[i]*i;
            y2+=a[i]*a[i]*i;
        }
        ll dx=x2-x1,dy=y2-y1;
        ll ans=0;
        if(dx==0&&dy==0){
            for(it=mp.begin();it!=mp.end();it++)
                ans+=((it->second)-1)*(it->second)/2;
        }
        else if(dx&&dy%dx==0){
            ll sum=dy/dx;
            for(ll i=1;i<=n;i++){
                ll aj=sum-a[i];
                if(aj-a[i]==0) continue;
                ll j=dx/(aj-a[i])+i;
                if(j>i&&j<=n&&aj==a[j]) ans++;
            }
        }
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41117236/article/details/89640765
今日推荐