码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5382 莫比乌斯反演

时间:2015-09-11 22:10:51      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:

 题目大意:

技术分享

求S(n)的值 n<=1000000

 

 

技术分享

 

这是官方题解给出的推导过程,orz,按这上面说的来写,就不难了

这里需要思考的就是G(n)这个如何利用积性函数的性质线性筛出来

作为一个质数,那么肯定G(i) = 2

1. 那么一个数 i 乘上了一个未出现的素数prime,那么就相当于,在当前符合的因子上面都乘了prime之后依旧符合,而原来 i 对应的数也符合,那么说明翻了两倍

也就是 g(i*prime) = 2*g(i) = g(prime) * g(i)

2. 如果这个乘上的素数prime已经存在于 i 中 , 那么仔细想一下,只有 i 那些符合的因子中已经带prime的必须再乘上这个prime,不然这个prime跑到 i/d中,gcd = prime了,其他的都不变,说明其实 g(i*prime) = g(i) 的

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 #define N 1000000
 5 #define ll long long
 6 const int MOD=258280327;
 7 
 8 ll g[N+5] , t[N+5] , f[N+5];
 9 ll sum[N+5];
10 int prime[N/5] , tot;
11 bool check[N+5];
12 
13 void get_g()
14 {
15     g[1] = 1;
16     for(int i=2 ; i<=N ; i++){
17         if(!check[i]) prime[tot++] = i , g[i] = 2;
18         for(int j=0 ; j<tot ; j++){
19             if((ll)prime[j]*i>N) break;
20             check[prime[j]*i] = true;
21             if(i%prime[j]) g[prime[j]*i] = g[prime[j]]*g[i];
22             else {g[prime[j]*i]=g[i]; break;}
23         }
24     }
25 }
26 
27 void get_t()
28 {
29     for(int k=2 ; k<=N ; k++)
30         for(int i=k ; i<=N ; i+=k)
31             t[i] = (t[i]+g[k-1])%MOD;
32 }
33 
34 void get_f()
35 {
36     for(int i=1 ; i<=N ; i++)
37         f[i] = (f[i-1]+2*i-1-t[i-1])%MOD;
38 }
39 
40 void init()
41 {
42     get_g();
43     get_t();
44     get_f();
45     for(int i=1 ; i<=N ; i++) sum[i] = (sum[i-1]+f[i])%MOD;
46 }
47 
48 int main()
49 {
50     //freopen("a.in" , "r" , stdin);
51     init();
52     int T , n;
53     scanf("%d" , &T);
54     while(T--){
55         scanf("%d" , &n);
56         printf("%I64d\n" , sum[n]);
57     }
58     return 0;
59 }

 

HDU 5382 莫比乌斯反演

标签:

原文地址:http://www.cnblogs.com/CSU3901130321/p/4802113.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!