2019年浙江省赛 B(ZOJ - 4101)解方程

题目传送门

题意:有一个a序列,a1............an,我们可以求出

,现在将a序列中任意两个数交换位置,变为b序列,现在给出b序列的顺序,给出x 和 y ,计算出对于b序列有几种交换方式,可以变成a序列。

解析: 我们设交换的两个数的下标为 i 和 j ,

则   x = a1 * 1 + a2 * 2 +...+ ai * i + ......+ aj * j +...an * n;

      y = a1 * a1 * 1 + a1 * a2 * 2 +...+ ai *ai * i + ......+ aj * aj * j +...+ an *an * n;

对于b序列来说,交换i 和 j:

xb   = a1 * 1 + a2 * 2 +...+ aj * i + ......+ ai * j +...an * n;

yb = a1 * a1 * 1 + a1 * a2 * 2 +...+ aj *aj * i + ......+ ai * ai * j +...+ an *an * n;

yb - y = (j - i) * (ai * ai - aj * aj)

xb - x = (j - i) * (ai -  aj)

(yb - y) /(xb - x) = ai + aj            

通过 (yb - y) /(xb - x) = ai + aj    和 xb - x = (j - i) * (ai -  aj) 这两个式子遍历每一数判断是否符合。

代码:

/*************************************************************************
	> File Name: 4101.cpp
	> Author: ccdxc
	> Mail: linyi0430@gmail.com
	> Created Time: 2019年05月07日 星期二 11时33分10秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#define ll long long 
#define pb push_back
using namespace std;
const int INF = 0x3f3f3f3f;
const int Maxn = 1e5 + 10;
int n , p[Maxn];
ll x , y, xb ,yb , ans  ,a[Maxn] ;
int main(){
    int T;
    cin >> T;
    while(T--){
        xb = yb = ans = 0;
        memset(p , 0 , sizeof(p));
        cin >> n >> x >> y;
        for(int i = 1;i <= n;i++){
            cin >> a[i];
            xb += i * a[i];
            yb += i * a[i] * a[i];
            p[a[i]]++;
        }
        if((y == yb && x != xb) || (y != yb && x == xb)){
            cout <<0 <<"\n";
            continue;
        }
        if(y == yb && x == xb){
            for(int i = 1;i <= n;i++)
                ans += p[a[i]] - 1;
            cout << ans/2 <<endl;
            continue;
        }
        ll tmp1 = yb -y , tmp2 = xb -x;
        if(tmp1 % tmp2 !=0){
            cout <<0 <<"\n";
            continue;
        }
        ll nu = tmp1 / tmp2;
        for(int i = 1;i <= n;i++){
            ll ar = nu - a[i];
            ll nf = ar - a[i];
            if(nf == 0) continue;
            if(tmp2 % nf != 0) continue;
            ll nt = i + tmp2 / nf;
                    //cout << nt <<endl;
            if(a[nt] == ar  && nt >= 1 && nt <= n) ans++;
            }
        ans /= 2;
        cout << ans <<endl;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值