zoukankan      html  css  js  c++  java
  • 【BZOJ3309】DZY Loves Math 解题报告

    【BZOJ3309】DZY Loves Math

    Description

    对于正整数(n),定义(f(n))(n)所含质因子的最大幂指数。例如(f(1960)=f(2^3×5^1×7^2)=3),(f(10007)=1),(f(1)=0)

    给定正整数(a,b),求(sumlimits_{a_i=1}sumlimits_{b_j=1}f(gcd(i,j)))

    Input

    第一行一个数(T),表示询问数。

    接下来(T)行,每行两个数(a,b),表示一个询问。

    Output

    对于每一个询问,输出一行一个非负整数作为回答。

    HINT

    (T≤10000)
    (1≤a,b≤10^7)


    推式子可以得到

    [sum_{T=1}^{min(a,b)}lfloorfrac{a}{T} floorlfloorfrac{b}{T} floorsum_{d|T}f(d)mu(frac{T}{d}) ]

    (g(T)=sum_{d|T}f(d)mu(frac{T}{d})),想一下卷积发现没啥用,然后我就放弃了。

    浪费了一次打表的大好机会...打表可以发现(g)只有(01)两种值,但是没什么显然的性质,于是我们可以暴力按意义分类讨论取(0)或者(1)

    然后我们讨论一下,设(p)代表质数

    • (g(p)=1)

    • 然后在计算式中令(frac{T}{d})的幂全为(0)(1),这样(mu)才能产生贡献。

      这样的话可以发现(f(d))只有两种取值(f(T))(f(T-1)),暴力讨论这两种取值。

      可以得到式子(g(T)=-sum_{d|x&&f(d) ot=f(x)}mu(frac{x}{d}))

      然后继续讨论可能取的(01)情况,发现如果幂全相等,可以取((-1)^{k+1})(k)为约数个数

      否则就取(0)

      线筛的时候维护一下最小质因子的幂数和最小质因子的幂


    Code:

    #include <cstdio>
    #include <algorithm>
    #define ll long long
    const int N=1e7;
    using std::min;
    int pri[N+10],ispri[N+10],a[N+10],b[N+10],cnt;
    ll f[N+10],ans,n,m;
    void init()
    {
        for(int i=2;i<=N;i++)
        {
            if(!ispri[i])
            {
                b[i]=pri[++cnt]=i;
                f[i]=a[i]=1;
            }
            for(int j=1;j<=cnt&&i*pri[j]<=N;j++)
            {
                ispri[i*pri[j]]=1;
                if(i%pri[j]==0)
                {
                    a[i*pri[j]]=a[i]+1;
                    b[i*pri[j]]=b[i]*pri[j];
                    if(i==b[i]) f[i*pri[j]]=1;
                    else f[i*pri[j]]=a[i/b[i]]==a[i]+1?-f[i/b[i]]:0;
                    break;
                }
                else
                {
                    a[i*pri[j]]=1,b[i*pri[j]]=pri[j];
                    f[i*pri[j]]=a[i]==1?-f[i]:0;
                }
            }
        }
        for(int i=1;i<=N;i++) f[i]+=f[i-1];
    }
    int main()
    {
        init();int T;scanf("%d",&T);
        while(T--)
        {
            ans=0;
            scanf("%lld%lld",&n,&m);
            for(ll l=1,r;l<=min(n,m);l=r+1)
            {
                r=min(n/(n/l),(m/(m/l)));
                ans+=(n/l)*(m/l)*(f[r]-f[l-1]);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    

    2018.12.15

  • 相关阅读:
    bzoj 1053
    bzoj 1004 组合
    字符串哈希
    bzoj 1015 并查集
    bzoj 1003 最短路+dp
    HDU 4352 数位dp
    bzoj 1879 状压dp
    codeforces 55D 数位dp
    Codeforces 830B
    组合计数 && Stirling数
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10124717.html
Copyright © 2011-2022 走看看