题解 P2508 [[HAOI2008]圆上的整点]

Guess00

2019-11-30 14:47:45

Solution

~~这是一道数学题~~ 高斯曾证明过这么一个东西$:$ > 设正整数$n=2^{a_0}p_1^{a_1}…p_s^{a_s}q_1^{b_1}…q_t^{b_t},$其中$p_1,…,p_s,q_1…q_t$是不同的质数$,p_i≡1\pmod{4}(1\leq i\leq s),q_j≡3\pmod{4}(1\leq j\leq t),$而$a_0,…a_s,b_1,…,b_t$是非负整数$.$则当$b_1,…,b_t$至少有一个为奇数时$,f(n)=0.$而当$b_1,…,b_t$都是偶数时$,f(n)=4(a_1+1)(a_2+1)…(a_s+1).$ 上述定理中$f(n)$函数表示方程$x^2+y^2=n$的正整数解个数$($证明过程略$,$太复杂$).$于是我们可以运用此定理$,$将题目中的$r$分解质因数$,$由于是$x^2+y^2=r^2,$所以$b_1…b_t$肯定都为偶数$,$答案为$4(2a_1+1)(2a_2+1)…(2a_s+1)$ $Pollard\_Rho,$复杂度是$\Theta(n^\frac{1}{4})(\text{就算r是1e+18都能过})$ $\mathbb{CODE:}$ ```cpp #include <bits/stdc++.h> #define int long long const int pri[]={2,3,5,7,11,13,17,23,29}; using std::vector; using std::sort; int n,i,j,cnt,ans=1; vector<int> v; inline void read(int &x) { short negative=1; x=0; char c=getchar(); while(c<'0' || c>'9') { if(c=='-') negative=-1; c=getchar(); } while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); x*=negative; } inline void print(int x) { if (x<0) putchar('-'),x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } inline int gcd(int a,int b){return b==0?a:gcd(b,a%b);} inline int ksc(int x,int y,int mod) { return (x*y-(long long)((long double)x/mod*y)*mod+mod)%mod; } inline int ksm(int a,int b,int m) { int ans=1; a%=m; while(b) { if(b&1) ans=ksc(a,ans,m); b/=2; a=ksc(a,a,m); } ans%=m; return ans; } inline bool MR(int x,int p) { if(ksm(x,p-1,p)!=1) return false; int k=p-1; while(!(k&1)) { k>>=1; int t=ksm(x,k,p); if(t!=1 && t!=p-1) return false; if(t==p-1) return true; } return true; } inline bool Miller_Rabin(int p) { if (p==1 || p==2152302898747) return false; for (int i=0;i<9;i++) if (p==pri[i]) return true; else if (p%pri[i]==0 || (!MR(pri[i],p))) return false; return true; } inline int Pollard_Rho(int n,int c) { int i=0,k=2,x=rand()%(n-1)+1,y=x; while(true) { i++; x=(x*x%n+c)%n; int d=gcd((y-x+n)%n,n); if(d!=1 && d!=n) return d; if(x==y) return n; if(i==k) y=x,k<<=1; } } inline void find(int x,int c) { if(x==1) return; if(Miller_Rabin(x)) { v.push_back(x); return; } int p=x; while(p>=x) p=Pollard_Rho(p,c--); find(p,c); find(x/p,c); } //MR,Miller_Rabin,Pollard_Rho,find函数是用来高效分解质因数的,存在一个vector中 //看不懂可以去看另一个代码,或者去P4718学习Pollard_Rho signed main(void) { read(n); find(n,200); sort(v.begin(),v.end()); for (i=0;i<v.size();i++) { j=i,cnt=1; while (i<v.size()-1 && v[j]==v[i+1]) //找相等质因数的个数 i++,cnt++; if (v[j]%4==1) //如果mod4=1,更新答案 ans*=(cnt*2+1); } print(ans*4); //输出 return 0; } ``` 正常分解是$\Theta(n^\frac{1}{2})$ $\mathbb{CODE:}$ ```cpp #include <bits/stdc++.h> #define int long long int n,i,cnt,ans=1; //ans初始赋为1,因为与坐标轴上有4个整点 inline void read(int &x) //快读 { short negative=1; x=0; char c=getchar(); while(c<'0' || c>'9') { if(c=='-') negative=-1; c=getchar(); } while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); x*=negative; } inline void print(int x) //快输 { if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } signed main(void) { read(n); for (i=2;i<=ceil(sqrt(n));i++) //因式分解,O(sqrt(n)) if (!(n%i)) { if (i%4==1) //如果i是个模4等于1的质数 { cnt=0; while (!(n%i)) cnt++,n/=i; //计算指数 ans*=(2*cnt+1); //更新答案 } while (!(n%i)) //把多余的除掉 n/=i; } if (n!=1 && n%4==1) //如果n是个模4等于1的质数 ans*=3; print(4*ans); //记得乘4 return 0; } ```