• [bzoj4176] Lucas的数论


    Description

    去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了。

    在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数。他现在长大了,题目也变难了。

    求如下表达式的值:

    [sum_{i=1}^nsum_{j=1}^nf(ij) ]

    其中 表示ij的约数个数。

    他发现答案有点大,只需要输出模1000000007的值。

    Input

    第一行一个整数n。

    Output

    一行一个整数ans,表示答案模1000000007的值。

    Sample Input

    2
    

    Sample Output

    8
    

    HINT

    对于100%的数据n <= 10^9。

    solution

    这题要求的东西其实和[bzoj3994] [SDOI2015]约数个数和是一样的,只是数据范围不同.

    由于这题(n)到了(1e9),考虑使用杜教筛.

    对于(f(n)=sum_{i=1}^{n}lfloorfrac{n}{i} floor),可以数论分块大力算一下.

    然后考虑(sum_{i=1}^{n}mu(i))怎么算.

    先把杜教筛的套路式搬出来:

    [S(n)=sum_{i=1}^{n}(f*g)(i)-sum_{i=2}^{n}g(i)S(lfloorfrac{n}{i} floor) ]

    其中,设(f(n)=mu(n))(S(n)=sum_{i=1}^nf(i))

    然后我们知道这样一个式子:

    [sum_{d|n}mu(d)=epsilon(n) ]

    其中(epsilon(n)=[n=1]),表示狄利克雷卷积的元函数.

    所以我们令(g(n)=1),即常函数,然后卷起来:

    [(f*g)(n)=sum_{d|n}f(d)g(frac{n}{d})=sum_{d|n}mu(d)=epsilon(n) ]

    所以(sum_{i=1}^{n}(f*g)(i)=1),即:

    [S(n)=1-sum_{i=2}^{n}S(lfloorfrac{n}{i} floor) ]

    然后递归求解,线筛出前(1e7)个,记忆化一下就做完了.

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
    	if(x<0) x=-x,putchar('-');
    	if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e7+1;
    const int mod = 1e9+7;
    
    int pri[maxn],vis[maxn],mu[maxn],n,tot;
    
    void sieve() {
    	mu[1]=1;
    	for(int i=2;i<maxn;i++) {
    		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
    		for(int t,j=1;j<=tot&&i*pri[j]<maxn;j++) {
    			vis[t=i*pri[j]]=1;
    			if(!(i%pri[j])) {mu[t]=0;break;}
    			mu[t]=-mu[i];
    		}
    	}
    	for(int i=1;i<maxn;i++) mu[i]=(mu[i-1]+mu[i])%mod;
    }
    
    map<int,int > Sum_mu;
    
    int sum_mu(int n) {
    	if(n<maxn) return mu[n];
    	if(Sum_mu[n]) return Sum_mu[n];
    	int T=2,res=1;
    	while(T<=n) {
    		int pre=T;T=n/(n/T);
    		res=(res-(T-pre+1)*sum_mu(n/T))%mod;T++;
    	}
    	return Sum_mu[n]=(res%mod+mod)%mod;
    }
    
    int calc(int n) {
    	int T=1,res=0;
    	while(T<=n) {
    		int pre=T;T=n/(n/T);
    		res=(res+(T-pre+1)*(n/T))%mod;T++;
    	}
    	return res;
    }
    
    signed main() {
    	sieve();
    	int n;read(n);
    	int T=1,ans=0;
    	while(T<=n) {
    		int pre=T;T=n/(n/T);int r=calc(n/T);
    		ans=(ans+(sum_mu(T)-sum_mu(pre-1))*r%mod*r%mod)%mod;T++;
    	}
    	write((ans%mod+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    删数问题
    八中公司_二分图带权最大匹配模板题
    完美子图(这道题太难了,得写下来要不回头又忘了)
    最近集训的图论(思路+实现)题目汇总(内容包含tarjan、分层图、拓扑、差分、奇怪的最短路):
    方格取数(简单版)+小烈送菜(不知道哪来的题)-----------奇怪的dp增加了!
    单调队列优化题:最大数(P1198)
    单调队列+线性dp题Watching Fireworks is Fun (CF372C)
    关于看了几道洛谷灰题(暂无评定)的感想
    洛谷的奇妙今日运势
    互不侵犯(洛谷P1896)
  • 原文地址:https://www.cnblogs.com/hbyer/p/10072917.html
Copyright © 2020-2023  润新知