题意:
原序列,通过交换其中两个元素的位置后,得到新序列。
定义函数:
已知原序列的x和y,还有交换元素位置后的新序列。
问有几种交换方案可以实现原序列到新序列的变换。
题解:
假设原序列的x、y为,新序列的为。
根据题意中x和y的表达式可以得出两个限制方程:
整理化简可以得到:
首先需要根据和分情况讨论,结果等于0的情况具体见代码。
- 当时说明原序列和新序列是相同的;
那么我们的交换方案需满足:;个数就是,m为序列中值为x的个数。
- 当时,
将两个方程式整理一下,消去,得到方程
根据上式,枚举i算出j的值,判断,根据判断是否符合条件。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; map<ll,ll> mp; map<ll,ll>::iterator it; ll a[100005]; int main() { int T; ll n; ll x1,x2,y1,y2,x; scanf("%d",&T); while(T--) { mp.clear(); ll num=0; x2=0,y2=0; scanf("%lld%lld%lld",&n,&x1,&y1); for(ll i=1; i<=n; i++) { scanf("%lld",&a[i]); x2+=i*a[i]; y2+=i*a[i]*a[i]; mp[a[i]]++; } if(((y1-y2)<0&&(x1-x2)>0)||((y1-y2)>0&&(x1-x2)<0)) { printf("0\n"); continue; } else if((x1==x2&&y1!=y2)||(x1!=x2&&y1==y2)) { printf("0\n"); continue; } else if(x1==x2&&y1==y2) { for(it=mp.begin(); it!=mp.end(); it++) { ll t1=(*it).first; if(mp[t1]>=2) num+=mp[t1]*(mp[t1]-1)/2; } printf("%lld\n",num); continue; } else if((abs(y1-y2))%(abs(x1-x2))!=0) { printf("0\n"); continue; } ll z=(y1-y2)/(x1-x2); for(int i=1; i<=n; i++) { if(2*a[i]==z) continue; int j=i-(x2-x1)/(2*a[i]-z); if(j>=1&&j<=n&&(i-j)*(a[i]-a[j])==(x2-x1)) num++; } printf("%lld\n",num/2); } return 0; }