Project Euler 531
题目
Chinese leftovers
Let $g(a,n,b,m)$ be the smallest non-negative solution $x$ to the system:
$\begin{aligned}
& x = a \bmod n\
& x = b \bmod m
\end{aligned}$
if such a solution exists, otherwise $0$.
E.g. $g(2,4,4,6)=10$, but $g(3,4,4,6)=0$.
Let $\varphi(n)$ be Euler’s totient function.
Let $f(n,m)=g(\varphi(n),n,\varphi(m),m)$.
Find $\sum f(n,m)$ for $1000000 \le n < m < 1005000$.
解决方案
题意比较裸,直接求出欧拉函数值然后通过中国剩余定理求方程的解即可。
当然也可以令$x=t_an+a=t_bm+b$,那么可以写出方程$t_an-t_bm=b-a$,只需要用一次扩展欧几里得算法就可以求出$t_a,t_b$,从而重新计算出$x$。这种做法比起使用中国剩余定理,少使用了一次扩展欧几里得算法,故也可以考虑。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| # include <bits/stdc++.h> using namespace std; typedef long long ll; const int L=1000000,R=1005000; int phi[R+4]; ll ex_gcd(ll a,ll b,ll &x,ll &y){ if(b==0){ x=1;y=0;return a; } ll g=ex_gcd(b,a%b,x,y); ll z=x-(a/b)*y; x=y;y=z;return g; }
ll congruence(ll a,ll c,ll m){ ll x,y,g; g=ex_gcd(a,m,x,y); if(c%g!=0) return -1; x*=c/g; ll t=m/g; return (x%t+t)%t; } ll CRT(ll b,ll m,ll c,ll n){ ll y=congruence(m,c-b,n); if(y==-1) return -1; ll x=m*y+b; ll t=m*n; return (x%t+t)%t; } int main(){ for(int i=1;i<R;i++) phi[i]=i; for(int i=2;i<R;i++){ if(phi[i]!=i) continue; phi[i]=i-1; for(int j=i+i;j<R;j+=i) phi[j]=phi[j]/i*(i-1); } ll ans=0; for(int i=L;i<R;i++){ for(int j=i+1;j<R;j++){ ll x=CRT(phi[i],i,phi[j],j); if(x!=-1) ans+=x; } } printf("%lld\n",ans); }
|