标签:ase 散列 == continue return ima std pre time
没学过二次剩余……比赛的时候想到了下面的方法(1591ms)。但是没特判$p=3$的情况,愉快的WA……
根据式子我们可以推到$a^2+ab+b^2=0 (mod p)$
当$a=b$的时候
$3a^2=0(mod p)$
当$p=3$的时候有解$a=1\ or\ a=2$
当$p \neq 3$的时候无解
当$a \neq b$的时候
不妨两边乘$(a-b)$得到$a^3-b^3=0 (mod p)$
就得到了散列函数$f(x)=x^3mod\;p$
结论也就出现了
$\begin{cases}a=b=1\ or\ a=b=2,p=3 \\f(a)=f(b),p \neq 3 \end{cases}$
注意数据范围,最大有$10^{18}$,立方的时候需要快速乘
样例1
6 3
0 1 1 2 2 2
- 1 1 2 2 2 逆元
- 1 1 2 2 2 $f(x)$
4
解集为$\{(1,1),(2,2),(2,2),(2,2)\}$
样例1
5 7
1 2 3 4 5 6
1 4 5 2 3 6 逆元
1 1 6 1 6 6 $f(x)$
6
解集为$\{(1,2),(1,4),(2,4),(3,5),(3,6),(5,6)\}$,都满足$f(a)=f(b),a \neq b$
样例3
5 7
1 1 2 2 4
1 1 4 4 2
1 1 1 1 1 $f(x)$
8
解集为$\{(1,2),(1,2),(1,4),(1,2),(1,2),(1,4),(2,4),(2,4)\}$,都满足$f(a)=f(b),a \neq b$
1 #include <map> 2 #include <set> 3 #include <queue> 4 #include <cmath> 5 #include <ctime> 6 #include <vector> 7 #include <cstdio> 8 #include <cstring> 9 #include <cstdlib> 10 #include <iostream> 11 #include <algorithm> 12 #define MAX 1000007 13 #define MAXN 10007 14 #define MAXM 20007 15 #define INF 0x3f3f3f3f 16 #define NINF 0xc0c0c0c0 17 #define MOD 1000000007 18 using namespace std; 19 typedef unsigned long long LL; 20 21 22 LL a[MAX],p; 23 int n; 24 LL Multi(LL a,LL b,LL m){ 25 LL ret = 0; 26 while(b){ 27 if(b&1) ret=(ret+a)%m; 28 b>>= 1; 29 a=(a<<1)%m; 30 } 31 return ret; 32 } 33 LL ac(LL x){ 35 return (x-1)*x/2; 36 } 37 map<LL,map<LL,LL> >M; 38 map<LL,LL>sum; 39 LL x; 40 int main(){ 43 int cas; 44 scanf("%d",&cas); 45 while(cas--){ 46 M.clear(); 47 sum.clear(); 48 scanf("%d%lld",&n,&p); 49 if(p==3){ 50 int xx,one=0,two=0; 51 for(int i=0;i<n;i++){ 52 scanf("%d",&xx); 53 if(xx==1)one++; 54 else if(xx==2)two++; 55 } 56 printf("%d\n",ac(one)+ac(two)); 57 continue; 58 } 59 LL num=0; 60 for(int i=0;i<n;i++){ 61 scanf("%lld",&x); 62 x%=p; 63 if(x==0)continue; 64 LL y=Multi(x,x,p); 65 y=Multi(x,y,p); 66 M[y][x]++; 67 sum[y]++; 68 num++; 69 } 70 LL ans=0; 71 map<LL,map<LL,LL> >::iterator it=M.begin(); 72 for(;it!=M.end();it++){ 73 //printf("%lld\n", it->first); 74 if(it->first==0)continue; 75 ans+=ac(sum[it->first]); 76 //printf("%lld %lld\n",sum[it->first],ans); 77 map<LL,LL>::iterator tt=it->second.begin(); 78 for(;tt!=it->second.end();tt++){ 79 ans-=ac(tt->second); 80 } 81 } 82 printf("%lld\n",ans); 83 } 84 return 0; 85 }
标签:ase 散列 == continue return ima std pre time
原文地址:http://www.cnblogs.com/shuiming/p/7368053.html