可爱女孩的二元组 【乘法逆元】
本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:
根据题意可知:
如果存在a[i],a[j]满足为Shmily Pair,
则可推出 (a[i]+a[j])(a[i]^2+a[j]^2)≡k
两边同时乘以a[i]-a[j]得 a[i]^4-a[j]^4≡k×a[i]-k×a[j]
所以a[i]^4-k×a[i]≡a[j]^4-k×a[j]
故对于任意两个数a[i],a[j]满足为Shmily Pair,则等效于a[i]^4-k×a[i]≡a[j]^4-k×a[j]
那么我们对于每一个值a[x],都将它进行一个这样的操作a[x]=(a[x]^4-k×a[x])%p
然后统计有多少对数满足这个条件就行了。
注意:逆元可以 + - × 的混合运算,但不能直接 ÷ 若果想要 ÷ 的话就乘其的倒数
法一:用sort直接比较
code:
1 #include<bits/stdc++.h> 2 #define int long long 3 #pragma GCC optimize(3) 4 const int N=5e6+10; 5 using namespace std; 6 int n,p,k; 7 int a[N],ans,sum; 8 void inint(){ 9 freopen("pairs.in","r",stdin); 10 freopen("pairs.out","w",stdout); 11 } 12 inline int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 16 return x*f; 17 } 18 inline void write(int x) 19 { 20 if(x<0)x=-x,putchar('-'); 21 if(x>9)write(x/10); 22 putchar(x%10+'0'); 23 } 24 signed main() 25 { 26 //inint(); 27 n=read(),p=read(),k=read(); 28 for(int i=1;i<=n;i++)a[i]=read(); 29 for(int i=1;i<=n;i++){ 30 a[i]=(((((((((a[i]%p)*a[i])%p)*a[i]%p)*a[i])%p)-(k*a[i]%p))+p)%p)%p; 31 } 32 sort(a+1,a+n+1); 33 for(int i=2;i<=n;i++){ 34 if(a[i]==a[i-1]){ 35 sum++; 36 ans+=sum; 37 } 38 else{ 39 sum=0; 40 } 41 } 42 printf("%lld\n",ans); 43 return 0; 44 }
法二:用map存储
code:
1 #include<bits/stdc++.h> 2 #define int long long 3 #pragma GCC optimize(3) 4 const int N=5e6+10; 5 using namespace std; 6 int n,p,k; 7 int a[N],ans,sum,yzl; 8 map<int,int>mv; 9 void inint(){ 10 freopen("pairs.in","r",stdin); 11 freopen("pairs.out","w",stdout); 12 } 13 inline int read(){ 14 int x=0,f=1;char ch=getchar(); 15 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 16 while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 17 return x*f; 18 } 19 inline void write(int x) 20 { 21 if(x<0)x=-x,putchar('-'); 22 if(x>9)write(x/10); 23 putchar(x%10+'0'); 24 } 25 signed main() 26 { 27 //inint(); 28 n=read(),p=read(),k=read(); 29 for(int i=1;i<=n;i++)a[i]=read(); 30 for(int i=1;i<=n;i++){ 31 int yzl=(((((((((a[i]%p)*a[i])%p)*a[i]%p)*a[i])%p)-(k*a[i]%p))+p)%p)%p; 32 ans+=mv[yzl]; 33 ++mv[yzl]; 34 35 } 36 printf("%lld\n",ans); 37 return 0; 38 }
注意:
1:应该边乘边模。
2:为了防止做减法时出现负数,我们可以先加上取模数,再来取模。
3:全开 long long 注意数据范围