【数论】【二次剩余】【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 ...
随机推荐
- “adb server is out of date.
今天,久未出现的著名的“adb server is out of date. killing”又发生了,在此,将解决方法记下,以便日后查看. 1. 错误信息: C:\Users\lizy>ad ...
- Spring注解@Resource和@Autowired区别对比、spring扫描的默认bean的Id、程序获取spring容器对象
-------------------------注解扫面的bean的ID问题-------------------------- 0.前提需要明白注解扫描出来的bean的id默认是类名首字母小写,当 ...
- 集合框架源码学习之LinkedList
0-1. 简介 0-2. 内部结构分析 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. 添加add方法 0-3-3. 根据位置取数据的方法 0-3-4. 根据对象得到索引 ...
- 从零开始PHP攻略(000)——关于WAMPServer集成环境
Apache.PHP和MySQL都可以用于多种操作系统和Web服务器的组合.本篇介绍在Windows下用WampServer环境包来搭建本地php环境. W:windows A:Apache M:My ...
- Linux 入门记录:三、Linux 文件基本操作管理
一.复制文件.目录 使用 cp 命令复制文件或目录: $ cp 源文件(夹)目标文件(夹) 常用参数: -r 递归复制整个目录树 -v 显示复制过程的详细信息 二.移动.重命名文件或目录 通过 mv ...
- AMD嵌入式G系列SoC协助优化Gizmo 2开发板
http://www.gizmosphere.org/ AMD嵌入式G系列SoC协助优化Gizmo 2开发板 http://news.zol.com.cn/491/4910444.html
- [收集]关于MSSQL数据库的一些查询
sqlserver快速查找所有存储过程中是否包含某字符 --将XXXX替换成你要查找的内容 select name from sysobjects o, syscomments s where o.i ...
- Eclipse和idea快捷键对比
花了一天时间熟悉IDEA的各种操作,将各种快捷键都试了一下,感觉很是不错!于是就整理了一下我经常用的一些Eclipse快捷键与IDEA的对比,方便像我一样使用Eclipse多年但想尝试些改变的同学们. ...
- ueditor在QQ浏览器或者IE浏览器中无法加载
因为IE浏览器有兼容问题,打开网址,浏览器不一定以最新的文档模式加载.按F12查看 在你网址的head标签中加入:<meta http-equiv="x-ua-compatible&q ...
- redis之(五)redis的散列类型的命令
[一]赋值与取值 -->命令:HSET key field value -->往某个key的某个属性设置值 -->命令:HGET key field --> 获取某个k ...