【BZOJ4176】 Lucas的数论

Description

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

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

求如下表达式的值:

其中 表示ij的约数个数。

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

Input

第一行一个整数n。

Output

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

Sample Input

2

Sample Output

8

HINT

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

Solution

因为直接用编辑器打公式比较麻烦且丑,就用markdown截图完传图片了= =b。

Code

 1 #include <cstdio>
 2 #include <cmath>
 3
 4 #define R register
 5 const int mod = 1e9 + 7;
 6 #define maxn 1500010
 7 int miu[maxn], smiu[maxn], pr[maxn / 10], prcnt, lim, N;
 8 bool vis[maxn];
 9 int hash[maxn];
10 bool vihash[50000];
11 int Miu(R int n)
12 {
13     if (n <= lim) return smiu[n];
14     if (vihash[N / n]) return hash[N / n];
15
16     vihash[N / n] = 1;
17     R int ret = 1;
18     for (R int i = 2, j; i <= n; i = j + 1)
19     {
20         j = n / (n / i);
21         (ret += mod - 1ll * (j - i + 1) * Miu(n / i) % mod) %= mod;
22     }
23     return hash[N / n] = ret;
24 }
25 inline int sumf(R int n)
26 {
27     R int ret = 0;
28     for (R int i = 1, j; i <= n; i = j + 1)
29     {
30         j = n / (n / i);
31         ret = (ret + 1ll * (j - i + 1) * (n / i)) % mod;
32     }
33     return ret;
34 }
35 int main()
36 {
37     scanf("%d", &N);
38     lim = (int) pow(N * 1.0, 0.666);
39 //    printf("%d\n", lim);
40     miu[1] = smiu[1] = 1;
41     for (R int i = 2; i <= lim; ++i)
42     {
43         if (!vis[i]) pr[++prcnt] = i, miu[i] = -1;
44         smiu[i] = (smiu[i - 1] + miu[i]) % mod;
45         for (R int j = 1; j <= prcnt && 1ll * i * pr[j] <= lim; ++j)
46         {
47             vis[i * pr[j]] = 1;
48             if (i % pr[j]) miu[i * pr[j]] = -miu[i];
49             else
50             {
51                 miu[i * pr[j]] = 0;
52                 break;
53             }
54         }
55     }
56     R int ans = 0, last = 0;
57     for (R int i = 1, j; i <= N; i = j + 1)
58     {
59         j = N / (N / i);
60         R int Ph = Miu(j);
61         R int fs = sumf(N / i);
62 //        printf("l = %d r = %d %d %d\n", i, j, Ph, fs);
63         ans = (ans + 1ll * (Ph - last + mod) * fs % mod * fs) % mod;
64         last = Ph;
65     }
66 //    printf("%d\n", last);
67     printf("%d\n", ans % mod);
68     return 0;
69 }
时间: 2024-08-07 00:01:45

【BZOJ4176】 Lucas的数论的相关文章

Bzoj4176 Lucas的数论

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 其中 表示ij的约数个数. 他发现答案有点大,只需要输出模1000000007的值. Input 第一行一个整数n. Output 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Ou

bzoj4176. Lucas的数论 杜教筛

题意:求\(\sum_{i=1}^n\sum_{j=1}^nd(ij),d是约数个数函数\) 题解:首先有一个结论\(d(ij)=\sum_{x|i}\sum_{y|j}[(i,j)==1]\) 那么\(\sum_{i=1}^n\sum_{j=1}^n\sum_{x|i}\sum_{y|j}\sum_{d|(i,j)}\mu(d)\) 枚举d,\(\sum_{i=1}^n\sum_{j=1}^n\sum_{d|i,d|j}\mu(d)d(\frac{i}{d})d(\frac{j}{d})=\s

bzoj 4176 Lucas的数论

bzoj 4176 Lucas的数论 和约数个数和那题差不多.只不过那个题是多组询问,这题只询问一次,并且 \(n\) 开到了 \(10^9\). \[ \begin{align*} \sum_{i=1}^N \sum_{j=1}^N f(ij)&= \sum_{i=1}^N \sum_{j=1}^N \sum_{x|i} \sum_{y|j}[gcd(x,y)=1]\\&= \sum_{i=1}^N \sum_{j=1}^N \sum_{x|i} \sum_{y|j} \sum_{d|g

【bzoj4176】Lucas的数论 莫比乌斯反演+杜教筛

题目描述 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 其中f(ij)表示ij的约数个数. 他发现答案有点大,只需要输出模1000000007的值. 输入 第一行一个整数n. 输出 一行一个整数ans,表示答案模1000000007的值. 样例输入 2 样例输出 8 题解 莫比乌斯反演+杜教筛 首先有个神奇

【bzoj 4176】 Lucas的数论 莫比乌斯反演(杜教筛)

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Output 8 HINT 对于100%的数据n <= 10^9. 题解: 解锁新技能:杜教筛. 再复习一下: 若$F(n)=\s

BZOJ 4176 Lucas的数论 莫比乌斯反演

题目大意:给定n(n≤109),求∑ni=1∑nj=1d(ij) 推错式子害死人... 由d|ij等价于dgcd(i,d)|j可得 ∑ni=1∑nj=1d(ij) =∑ni=1∑n2d=1?n?gcd(i,d)d? =∑nd=1∑?nd?i=1∑?n2d?j=1?nj?[gcd(i,j)=1] =∑nd=1∑?nd?i=1∑nj=1?nj?[gcd(i,j)=1] =∑nd=1∑?nd?i=1∑nj=1?nj?∑k|i,k|jμ(k) =∑nk=1μ(k)(∑?nk?d=1?nkd?)2 O(n

数论专项测试——约数个数和(lucas的数论)

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 typedef long long int64; 8 const int mod=1000000007; 9 #define maxn 2000005 10 int top,tot,d[ma

●BZOJ 4176 Lucas的数论

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4176 题解: 莫比乌斯反演,杜教筛 首先有这么一个结论: 令d(n)表示n的约数的个数(就是题目中的f(n)),则有 $$d(nm)=\sum_{i|n}\sum_{j|m}[gcd(i,j)==1]$$ ●BZOJ 3994 [SDOI2015]约数个数和也用到了这个东西. 那么就下来接直接进行求ANS的式子的推导: $$\begin{aligned}ANS&=\sum_{n=1}^{N

【算法总结】积性函数相关

[线性筛] [模板代码] [线性筛质数] 1 int main() 2 { 3 n=read(); 4 for(int i=2;i<=n;i++) 5 { 6 if(!f[i])pri[++cnt]=i; 7 for(int j=1;j<=cnt;j++) 8 { 9 if(i*pri[j]>n)break; 10 f[i*pri[j]]=1; 11 if(i%pri[j]==0)break; 12 } 13 } 14 } [线性求约数和] 1 void pre() 2 { 3 miu[