ZOJ4101Element Swapping (数学+思维)

Element Swapping
Time Limit: 1 Second Memory Limit: 65536 KB
DreamGrid has an integer sequence and he likes it very much. Unfortunately, his naughty roommate BaoBao swapped two elements and () in the sequence when DreamGrid wasn’t at home. When DreamGrid comes back, he finds with dismay that his precious sequence has been changed into !

What’s worse is that DreamGrid cannot remember his precious sequence. What he only remembers are the two values
Given the sequence after swapping and the two values DreamGrid remembers, please help DreamGrid count the number of possible element pairs BaoBao swaps.

Note that as DreamGrid is poor at memorizing numbers, the value of or might not match the sequence, and no possible element pair can be found in this situation.

Two element pairs () and () are considered different if or .

Input
There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:

The first line contains three integers , and (), indicating the length of the sequence and the two values DreamGrid remembers.

The second line contains integers (), indicating the sequence after swapping. It’s guaranteed that and .

It’s guaranteed that the sum of of all test cases will not exceed .

Output
For each test case output one line containing one integer, indicating the number of possible element pairs BaoBao swaps.

Sample Input
2
6 61 237
1 1 4 5 1 4
3 20190429 92409102
1 2 3
Sample Output
2
0
Hint
For the first sample test case, it’s possible that BaoBao swaps the 2nd and the 3rd element, or the 5th and the 6th element.

Author: WENG, Caizhi
Source: The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple

在这里插入图片描述

题目大意:数组a通过交换一对数字,得到了b数组,给出如下的两个值
问可能有多少种交换方式使得满足条件,x和y的值有可能是和数组不匹配的,这样的情况时输出0

思路:
求出交换后的数组的x1和y1,(y1-y)/(x1-x)即为交换的两个数的和
如果, (y1-y)和(x1-x)不是倍数关系,则证明是不匹配的
如果,(x1-x)== 0,则证明交换的是两个相同的数,如果y1和y不相等,则证明是不匹配的
如果y1和y相等,那么就是匹配的,此时只需要找有多少对相同的数即可

预先求出一个 aj =(y1-y)/(x1-x) - a[ i ]
x2-x = ( b[ j ] - b[ i ] )* ( j - i ),假设 j 比 i 大
如果,b[j] - b[i] 是 0 ,continue;
可以通过上面这个式子求出 j 是多少,再检查这个位置的b [ j ] 和我们预先求出的 aj 是不是相等的

笔记:
1.求出公式a[i]+a[j]为定值,根据 i 得出 j 也为定值,计算得出的 j 对应的a[j]是否等于 算出的 a[i]+a[j]-a[i]的a[j]
2.考虑xsum1和ysum2的情况,同时等于,说明交换相同数字,求出c(i,2)每个数字选两个,用num数组计算数字出现次数。有一个相同另一个不相同不可能输出0。
3.不相等情况,每次都要注意是否可以整除,越界,大于0,j>i
4.全部定义为long long ,记得所有输入用%lld ,这里T定义long long,输入用%d,wa了无数发。数组单独定义在一起,尽量不要和变量一起定义。不然会出现迷之可能越界bug,这里两个数组定义,中间间隔了变量,就wa了,数组要定义在一起才行。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll x,y,T,n,aj,t,k,j,sum1,sum2,ans;
ll a[maxn],num[maxn];

int main()
{
    scanf("%lld",&T);
    while(T--)
    {
        sum1=0,sum2=0,ans=0;
        memset(num,0,sizeof(num));
        scanf("%lld%lld%lld",&n,&x,&y);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            sum1+=(ll)i*a[i];
            sum2+=(ll)i*a[i]*a[i];
            num[a[i]]++;
        }
        if(x==sum1&&y==sum2)
        {
            for(int i=1;i<=maxn;i++)
            {
                ans+=(num[i]-1)*num[i]/2;

            }
            cout << ans << endl;
            continue;
        }
        if(x==sum1||y==sum2)
        {
            cout << 0 << endl;
            continue;
        }
        if((y-sum2)%(x-sum1)!=0)
        {
            cout << 0 << endl;
            continue;
        }
        k=(y-sum2)/(x-sum1);
        for(int i=1;i<=n;i++)
        {
            aj=k-a[i];
            t=aj-a[i];
            if(t!=0&&k-a[i]>0&&(x-sum1)%t==0)
            {
                j=i-(x-sum1)/t;
                if(j<=n&&j>i&&a[j]==aj)
                {
                    ans++;
                }
            }
        }
        cout << ans << endl;
    }

    return 0;
}

``


猜你喜欢

转载自blog.csdn.net/w1304636468/article/details/89932097