zoukankan      html  css  js  c++  java
  • BZOJ 4176 Lucas的数论

    反演就告一段落啦。。。

    这题主要是化式子需要灵活。。。主要有交换Σ,减小枚举范围两个技巧。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define maxn 5000050
    #define mod 1000000007
    using namespace std;
    int n,miu[maxn],prime[maxn],tot=0,ans=0;
    bool vis[maxn];
    map <int,int> mp;
    void get_table()
    {
        miu[1]=1;
        for (int i=2;i<=maxn-50;i++)
        {
            if (!vis[i])
            {
                vis[i]=true;
                prime[++tot]=i;miu[i]=-1;
            }
            for (int j=1;j<=tot && i*prime[j]<=maxn-50;j++)
            {
                 vis[i*prime[j]]=true;
                 if (i%prime[j]) miu[i*prime[j]]=-miu[i];
                 else {miu[i*prime[j]]=0;break;}
            }
        }
        for (int i=2;i<=maxn-50;i++) miu[i]+=miu[i-1];
    }
    int ask(int n)
    {
        if (n<=maxn-50) return miu[n];
        if (mp.find(n)!=mp.end()) return mp[n];
        int ret=1,l=2,r;
        while (l<=n)
        {
            r=n/(n/l);
            ret=(ret-(long long)ask(n/l)*(r-l+1)+mod)%mod;
            l=r+1;
        }
        mp[n]=ret;return ret;
    }
    int main()
    {
        scanf("%d",&n);get_table();
        int l=1,r;
        while (l<=n)
        {
            r=n/(n/l);
            int top=n/l,l1=1,r1,ret=0;
            while (l1<=top) {r1=top/(top/l1);ret=(ret+(long long)top/l1*(r1-l1+1)%mod)%mod;l1=r1+1;}
            ret=(long long)ret*ret%mod;
            ans=(ans+(long long)(ask(r)-ask(l-1)+mod)%mod*ret%mod)%mod;
            l=r+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    LeetCode 104
    LeetCode 100
    LeetCode 27
    LeetCode 7
    LeetCode 8
    蘑菇街2017春招笔试
    codeforces 5D
    codeforces 5C
    codeforces 875B
    codeforces 876B
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6510264.html
Copyright © 2011-2022 走看看