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

传送门

题意:数组a通过交换一对数字,得到了b数组,给出x=∑nk=1kak和y=∑nk=1ka2k和b数组,问有多少对l,r(l<=r)能满足条件
 

思路:

假设交换了 (i,j),那么:i*a[i] -> i*a[j],j*a[j] -> j*a[i]

因此对于原来的 x、y 有:

\left\{\begin{matrix}X=(i-j)*(a[j]-a[i])+\sum_{i=1}^nk*a[i]=(i-j)*(a[j]-a[i])+x \\ Y=(i-j)*(a[j]^2-a[i]^2)+\sum_{i=1}^nk*a[i]^2=(i-j)*(a[j]^2-a[i]^2)+y \end{matrix}\right.

可以得到:

\left\{\begin{matrix}X-x=(i-j)*(a[j]-a[i]) \\ Y-y=(i-j)*(a[j]^2-a[i]^2) \end{matrix}\right.

将得到的两个式子相除,有:\frac{Y-y}{X-x}=a[i]+a[j]

第一个式子可以化简为 X−x=(ai−aj)∗(j−i)

  • 第一个式子左边为一个定值,所以ai和aj一一对应,可以枚举a数组
  • 第二个数组可以化为X2−X1+(bj−bi)ibj−bi=j\frac{X-x+(aj-ai)*i}{aj-ai},假设j>i(方便计数),枚举ai通过式子一可以计算aj,然后通过式子二可以计算出j,判一下aj是否等于j
  • X2−X1=0,Y2−Y1≠0,则不合法
  • X2−X1=0,Y2−Y1=0推出ai=aj,j≠i
     
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<map>
    #define ll long long
    #define N 0x3f3f3f3f
    using namespace std;
    ll a[100010];
    int main()
    {
    	int t;
    	scanf("%d",&t);
    	while(t--)
    	{
    		int n;
    		map<ll,ll>mp;
    		ll x,y;
    		scanf("%d%lld%lld",&n,&x,&y);
    		ll x1=0,y1=0;
    		ll minn=N;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%lld",&a[i]);
    			mp[a[i]]++;
    			x1=x1+i*a[i];
    			y1=y1+i*a[i]*a[i];
    		}
    		ll A=x1-x,B=y1-y;;
    		if(A==0)
    		{
    			if(B!=0)
    			{
    				cout<<0<<endl;
    				continue;
    			}
    			ll sum=0;
    			map<ll,ll>::iterator it;
    			for(it=mp.begin();it!=mp.end();it++)
    			{
    				sum+=((it->second)-1)*(it->second)/2;
    			}
    			printf("%lld\n",sum);
    			continue;
    		}
    		if(B%A)
    		{
    			printf("0\n");
    			continue;
    		}
    		ll dt=B/A,sum=0;
    		for(int i=1;i<=n;i++)
    		{
    			ll aj=dt-a[i];
    			if(aj==a[i])
    			continue;
    			ll j=(A+(aj-a[i])*i)/(aj-a[i]);
    			if(j<=i||j>n)
    			continue;
    			if(a[j]==aj)
    			sum++;
    		}
    		printf("%lld\n",sum);
    	}
    	return 0;
    }

    不知道为啥 数组a 我定义成int类型的就wa 0.0 明明数组范围是 10^6 

展开阅读全文

没有更多推荐了,返回首页