• luogu 4844 LJJ爱数数 (莫比乌斯反演+数学推导)


    题目大意:求满足gcd(a,b,c)==1,1/a+1/b=1/c,a,b,c<=n的{a,b,c}有序三元组个数

    因为题目里有LJJ我才做的这道题

    出题人官方题解https://www.cnblogs.com/Blog-of-Eden/p/9367521.html对我帮助很大

    思维很巧妙的一道题,佩服出题人Orzzz

    由原式可得,$c=frac{ab}{a+b}$

    令g=gcd(a,b),A=a/g,B=b/g,显然gcd(g,c)==1,gcd(A,B)==1

    带入可得$frac{ABg^{2}}{(A+B)g}=c$ <=> $frac{ABg}{A+B}=c$

    因为A,B互质,所以$A,B,A+B$两两互质

    由$frac{ABg}{A+B}=c$可得

    因为c是整数,A与A+B互质,B与$A+B互质,所以当且仅当(A+B)|g

    令G=g/(A+B),可得ABG=c,所以G|c,而g与c互质,所以G作为g的因子,与c也一定互质,即gcd(G,c)==1,所以G只能等于1

    综上,可得g=A+B,c=AB,a+b=$g^{2}$

    现在大问题转化成了一般性问题,每次枚举一个g,求在一定范围内,g=A+B且gcd(A,B)==1的数对数量

    显然这样的数对数量可以用莫比乌斯反演求得

    由于g<=$sqrt(2n)$,g<$2*10^{6}$,通过预处理,分解质因数是时间可以优化成logn,再筛出它所有的因子,利用莫比乌斯函数的容斥性质,即可求得合法数对数量

    筛出每个数的因子的时间是均摊logn(调和级数),但由于空间限制,不能预处理出每个数的所有因子..

    而A的合法范围则是保证A<=g,A*g<=n&&B*g<=n

    细节需要多思考

     1 #include <cmath>
     2 #include <vector>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 #define N 2001000
     7 #define maxn 2000000
     8 #define ll long long 
     9 #define uint unsigned int
    10 using namespace std;
    11 
    12 ll n;
    13 int cnt;
    14 
    15 int pr[N],use[N],mu[N],pmu[N],nxt[N];
    16 void get_pr()
    17 {
    18     mu[1]=pmu[1]=1;
    19     for(int i=2;i<=maxn;i++)
    20     {
    21         if(!use[i]) pr[++cnt]=i,nxt[i]=i,mu[i]=-1;
    22         pmu[i]=pmu[i-1]+mu[i];
    23         for(int j=1;j<=cnt&&i*pr[j]<=maxn;j++){
    24             use[i*pr[j]]=1,nxt[i*pr[j]]=pr[j];
    25             if(i%pr[j]==0){
    26                 mu[i*pr[j]]=0;
    27                 break;
    28             }else{
    29                 mu[i*pr[j]]=-mu[i];
    30             }
    31         }
    32     }
    33 }
    34 int son[N],d[N],ps[N],num,nson;
    35 void dfs_son(int s,int dep)
    36 {
    37     if(dep>num) {son[++nson]=s;return;}
    38     for(int j=0;j<=d[dep];j++)
    39         dfs_son(s,dep+1),s*=ps[dep];
    40 }
    41 void get_son(int x)
    42 {
    43     num=0;
    44     while(x!=1){
    45         int p=nxt[x];ps[++num]=p;d[num]=0;
    46         while(x%p==0) x/=p,d[num]++; 
    47     }
    48     if(x!=1) ps[++num]=x,d[num]=1;
    49     for(int i=1;i<=nson;i++) son[i]=0;
    50     nson=0;
    51     dfs_son(1,1);
    52 }
    53 ll solve(int l,int r,int g)
    54 {
    55     ll ans=0;l--;
    56     get_son(g);
    57     for(int i=1;i<=nson;i++)
    58         ans+=1ll*mu[son[i]]*(r/son[i]-l/son[i]);
    59     return ans;
    60 }
    61 
    62 int main()
    63 {
    64     //freopen("t1.in","r",stdin);
    65     scanf("%lld",&n);
    66     ll sq=sqrt(n*2);
    67     get_pr();
    68     ll ans=0;
    69     for(ll g=1;g<=sq;g++)
    70     {
    71         int l=max(1ll,((g*g-n)/g+( ((g*g-n)%g==0)?0:1 )));
    72         int r=min(g-1,n/g);
    73         if(l>r) continue;
    74         ans+=solve(l,r,g);
    75     }
    76     printf("%lld
    ",ans);
    77     return 0;
    78 }
  • 相关阅读:
    Stacks And Queues
    Programming Assignment 5: Burrows–Wheeler Data Compression
    Data Compression
    Regular Expressions
    Programming Assignment 4: Boggle
    Oracle 查询表的索引包含的字段
    pycharm
    Java文件:追加内容到文本文件
    okhttp 使用response.body().string()获取到的数据是一堆乱码
    彻底解决unable to find valid certification path to requested target
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9984837.html
Copyright © 2020-2023  润新知