【数论】【二次剩余】【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 ...
随机推荐
- [bzoj1070] 修车
这周学习了费用流,就写了几题.其中有一题就是bzoj上的修车,看起来很丧,交了6次都是除了样例全wa(事实证明样例说明不了什么,还会误导你……). 题目大意:有m个技术人员n辆车,一个技术人员只能同时 ...
- Python3 面向对象编程
小案例: #!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Bert import sys class Role(object): n=&qu ...
- [Leetcode Week15]Populating Next Right Pointers in Each Node II
Populating Next Right Pointers in Each Node II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/popul ...
- notifier chain — 内核通知链【转】
转自:http://blog.csdn.net/g_salamander/article/details/8081724 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣 ...
- sql server查看创建表的代码,表定义
1.查看建表语句在“对象资源管理器”中找到要导出的表,选中该表并单击右键,“编写表脚本为(S)”/“CREATE到(C)”/“新查询编辑器窗口”即可查看该表的建表语句.2.导出建表语句在“对象资源管理 ...
- 相册框架之AssetsLibrary
看到项目中用到AssetsLibrary这个框架, 所以研究了一下 其实很简单 - (void)getAlbumPhoto { NSString *tipTextWhenNoPhotosAuthori ...
- 创建.dat文件(转载)
比较有用的东比较有用的东西 首先,批处理文件是一个文本文件,这个文件的每一行都是一条DOS命令(大部分时候就好象我们在DOS提示符下执行的命令行一样),你可以使用DOS下的Edit或者Windows的 ...
- MySQL:按后缀缀批量删除表格
Select CONCAT( 'drop table ', table_name, ';' ) FROM information_schema.tables Where table_schema='s ...
- jq监听ajax执行开始,出错,结束。
$(“#msg”).ajaxComplete(function(event,request, settings){ $(this).append(“<li>请求完成.</li&g ...
- sql server 2008 R2无法连接127.0.0.1报错 Server error:40(错误:53)
在公司用sql server 2008 R2很好的,回家连接127.0.0.1就报错.sql server2008R2主机名和.都可以登录,连接127.0.0.1出错,在与 SQL Server 建立 ...