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 49 50 51
| 2-友善数 如果正整数a和b满足\text{gcd}(a,b)=2^t,t>0,则称它们互为2-友善数。例如,24和40互为2-友善数,因为\text{gcd}(24,40)=8=2^3;而24和36则不是,因为\text{gcd}(24,36)=12=2^2\cdot 3不是2的幂。
考虑所有满足1\le p<q\le n且p和q互为2-友善数的正整数对(p,q),并记这些数对的数目为f(n)。已知f(10^2)=1031,f(10^6)对1\ 000\ 000\ 007取余的结果为321418433.
Find f(10^{11})并对1\ 000\ 000\ 007取余。
这是个经典的莫比乌斯反演,可以套数论分块+线性筛. 枚举gcd()=x,枚举x会缩小pq的取值范围从1e11缩小到floor(1e11/x),其中x是2的幂. 这样问题转化为指定区间[1,n]上有多少个数对互质,用线性筛处理sqrt n以内的莫比乌斯函数再套上前缀和与数论分块,容斥一下就可以了.
参考欧拉筛实现: int vis[1000010];//存最小质因数,负的表示质数表中的位置(负的) int p[100010],ptop=0;//存质数 short mu[1000010];//莫比乌斯函数 int musu[1000010];//梅滕斯函数,莫比乌斯前缀和 int phi[1000010];//欧拉函数 long long phisu[1000010];//欧拉函数前缀和 int d[1000010];//存每个数的约数个数 int mnnum[1000010];//最小质因子出现次数 void sieve(int n){//[1,n] phi[1]=1;phisu[1]=1;mu[1]=1;musu[1]=1;d[1]=1; int tmp; for(int i=2;i<=n;++i){ if(!vis[i]){ vis[i]=-(++ptop); p[ptop]=i; mu[i]=-1;// phi[i]=i-1;// d[i]=2;// mnnum[i]=1;// } for(int j=1;j<=ptop&&i*p[j]<=n;++j){ vis[i*p[j]]=p[j]; if(i%p[j]==0){ phi[i*p[j]]=phi[i]*p[j];// mnnum[i*p[j]]=mnnum[i]+1;// d[i*p[j]]=d[i]/mnnum[i*p[j]]*(mnnum[i*p[j]]+1);// break; }else{ mu[i*p[j]]=-mu[i];// phi[i*p[j]]=phi[i]*(p[j]-1);// mnnum[i*p[j]]=1;// d[i*p[j]]=d[i]*2;// } } musu[i]=musu[i-1]+mu[i];// phisu[i]=phisu[i-1]+phi[i];// } }
|