【数论】【二次剩余】【map】hdu6128 Inverse of sum
部分引用自:http://blog.csdn.net/v5zsq/article/details/77255048


所以假设方程 x^2+x+1=0 在模p意义下的解为d,则答案就是满足(ai/aj) mod p = d的数对(i,j)的数量(i<j)。
现在把问题转化为解这个模意义下的二次方程。
x^2+x+1=0
配方:x^2+x+1/4+3/4=0
(x+1/2)^2+3/4=0
同乘4:(2x+1)^2+3=0
即(2x+1)^2=-3 (mod p)
换句话说,我们必须保证-3+p是p的一个二次剩余。
倘若-3+p不是p的一个二次剩余的话,无解。
如果是的话,我们就可以通过Cipolla算法得到2x+1的两个可能值,也就把二次同余方程变成了两个线性同余方程。
然后在一般情况下可以通过扩展欧几里得算法求得这两个个线性同余方程的最小非负整数解,也就得到了这个二次同余方程的两个解。
不过这题的情况有点特别,形式非常简单,根据大神的总结,在我们得到2x+1的两个值d1、d2之后,可以这样得到x1、x2。

于是我们可以通过枚举+map来得到点对的个数。
注意特殊情况:①倘若x1或者x2为零的话,意味着(ai/aj)mod p=0,这是不可能的,注意不要统计这种。
②p为2时无解。
③p为3时有解,但是由于p-3等于零,所以不能直接用上面的方法。不过经过简单的推导,我们发现唯一合法的情况是ai=aj,且ai、aj均不为零,直接特判掉。
求解二次剩余的Cipolla算法:
http://blog.csdn.net/a_crazy_czy/article/details/51959546
http://blog.csdn.net/philipsweng/article/details/50000903
一句话:通过勒让德符号来判断n是不是模p的二次剩余,然后random一个a,使得(a^2-n)不是二次剩余,然后通过复数快速幂来求二次剩余的值。


#include<cstdio>
#include<map>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
ll p,a[200005];
struct Complex{
ll a,b;
Complex(const ll &a,const ll &b){
this->a=a;
this->b=b;
}
Complex(){}
};
map<ll,int>ma;
int T,n;
ll Quick_Mul(ll x,ll p,ll mod){
if(!p){
return 0ll;
}
ll res=Quick_Mul(x,p>>1,mod);
res=(res+res)%mod;
if((p&1ll)==1ll){
res=(x%mod+res)%mod;
}
return res;
}
ll Quick_Pow(ll x,ll p,ll mod){
if(!p){
return 1ll;
}
ll res=Quick_Pow(x,p>>1,mod);
res=Quick_Mul(res,res,mod);
if((p&1ll)==1ll){
res=Quick_Mul(x%mod,res,mod);
}
return res;
}
ll aa,nn;
Complex Complex_Mul(const Complex &A,const Complex &B,const ll &p){
return Complex((Quick_Mul(A.a,B.a,p)+Quick_Mul(Quick_Mul(A.b,B.b,p),(Quick_Mul(aa,aa,p)-nn+p)%p,p))%p,
(Quick_Mul(A.a,B.b,p)+Quick_Mul(A.b,B.a,p))%p);
}
Complex Complex_Quick_Pow(Complex x,ll p,ll mod){
if(!p){
return Complex(1ll,0ll);
}
Complex res=Complex_Quick_Pow(x,p>>1,mod);
res=Complex_Mul(res,res,mod);
if((p&1ll)==1ll){
res=Complex_Mul(x,res,mod);
}
return res;
}
ll ran1(){
return ((rand()<<16)|rand());
}
ll ran(){
return ((ran1()<<16)|ran1());
}
pair<ll,ll> work(ll n,ll p){
aa=ran()%p;
nn=n;
while(Quick_Pow((Quick_Mul(aa,aa,p)-n+p)%p,(p-1ll)/2ll,p)!=p-1ll){
aa=ran()%p;
}
ll res=Complex_Quick_Pow(Complex(aa,1ll),(p+1ll)/2ll,p).a;
return make_pair(res,p-res);
}
ll ans;
ll f(ll x,ll p){
return (x&1ll)==1ll ? (x-1ll)/2ll : (x-1ll+p)/2ll;
}
int main(){
// freopen("1009.in","r",stdin);
// freopen("hdu6128.out","w",stdout);
srand(233);
scanf("%d",&T);
for(;T;--T){
ans=0;
ma.clear();
scanf("%d%lld",&n,&p);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
}
if(p==2ll || Quick_Pow(p-3ll,(p-1ll)/2ll,p)==p-1ll){
puts("0");
continue;
}
if(p==3ll){
for(int i=1;i<=n;++i){
if(a[i]){
ans+=ma[a[i]];
}
++ma[a[i]];
}
printf("%lld\n",ans);
continue;
}
pair<ll,ll> d=work(p-3ll,p);
d.first=f(d.first,p);
d.second=f(d.second,p);
for(int i=1;i<=n;++i){
if(d.first){
ans+=ma[Quick_Mul(a[i],d.first%p,p)];
}
if(d.second){
ans+=ma[Quick_Mul(a[i],d.second%p,p)];
}
if(a[i]){
++ma[a[i]];
}
}
printf("%lld\n",ans);
}
return 0;
}
【数论】【二次剩余】【map】hdu6128 Inverse of sum的更多相关文章
- 2017多校第7场 HDU 6128 Inverse of sum 推公式或者二次剩余
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6128 题意:给你n个数,问你有多少对i,j,满足i<j,并且1/(ai+aj)=1/ai+1/a ...
- 数学--数论--HDU 6128 Inverse of sum (公式推导论)
Description 给nn个小于pp的非负整数a1,-,na1,-,n,问有多少对(i,j)(1≤i<j≤n)(i,j)(1≤i<j≤n)模pp在意义下满足1ai+aj≡1ai+1aj ...
- 2017ACM暑期多校联合训练 - Team 7 1009 HDU 6128 Inverse of sum (数学计算)
题目链接 Problem Description There are n nonnegative integers a1-n which are less than p. HazelFan wants ...
- [zoj 3774]Power of Fibonacci 数论(二次剩余 拓展欧几里得 等比数列求和)
Power of Fibonacci Time Limit: 5 Seconds Memory Limit: 65536 KB In mathematics, Fibonacci numbe ...
- HDU 6128 Inverse of sum(同余)
http://acm.hdu.edu.cn/showproblem.php?pid=6128 题意:有一个a数列,并且每个数都小于p,现在要求有多少对$(i,j)$满足$\frac{1}{a_i+a_ ...
- apache_commons 之 双向Map DualHashBidiMap (使用及源码)
在项目当中,经常出现需要根据Key值获取value:而且要求根据value获取key值,其实在commons-collections包中已经提供了此集合类.就是DualHashBidiMap类. (官 ...
- Leetcode: Path Sum III
You are given a binary tree in which each node contains an integer value. Find the number of paths t ...
- 325. Maximum Size Subarray Sum Equals k
最后更新 二刷 木有头绪啊.. 看答案明白了. 用的是two sum的思路. 比如最终找到一个区间,[i,j]满足sum = k,这个去见可以看做是 [0,j]的sum 减去 [0,i]的Sum. 维 ...
- [leetcode-508-Most Frequent Subtree Sum]
Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a ...
随机推荐
- 随机生成数组函数+nth-element函数
这几天做了几道随机生成数组的题,且需要用nth-elemeng函数,并且都是北航出的多校题…… 首先我们先贴一下随机生成数组函数的代码: unsigned x = A, y = B, z = C; u ...
- .NET Core Data Access
.NET Core was released a few months ago, and data access libraries for most databases, both relation ...
- centos7安装libvirt支持xen
另外还有一个非常棒的用法 假如我要执行iostat这个命令来查看CPU与存储设备状态,可是执行却发现没有这个命令 于是执行yum install iostat,结果说找不到该软件,使用下面的办法可以解 ...
- CNN中千奇百怪的卷积方式大汇总
1.原始版本 最早的卷积方式还没有任何骚套路,那就也没什么好说的了. 见下图,原始的conv操作可以看做一个2D版本的无隐层神经网络. 附上一个卷积详细流程: [TensorFlow]tf.nn.co ...
- 谈谈mybatis逆向工程中的Example类
参考博客: http://openwares.net/database/mybatis_generator_example.html 一.Example类的作用:一个用于筛选复杂条件的类 二.Exam ...
- Linux 日志系统及分析
简介 在Centos 7.x / RHEL 7.x 的版本,系统日志是由一个名为 rsyslog的服务管理的,默认的日志守护进程为 rsyslog , rsyslog 是 syslog 的升级版本,默 ...
- date 时间确定
获取当前时间: var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; var d ...
- IntelJ IDEA 进行Java Web开发+热部署+一些开发上的问题
基本上像放弃MyEclipse或者Eclipse了,因为IDEA现在也有对应的版本旗舰版和社区版了,而且使用更贴心,更给力,为什么还要选一个难用的要死的东西呢? 最近要开发一个Java Web项目,所 ...
- LocalStorage、SessionStorage使用详解
https://blog.csdn.net/zhongzh86/article/details/55504381
- 【JBPM4】流程分支fork - join
流程分支.聚合.流程每个分支节点都全部处理完成后,聚合到下一个节点. JPDL <?xml version="1.0" encoding="UTF-8"? ...