[机房练习赛4.6] mulfunc 线性筛

来源:互联网 发布:c语言俄罗斯方块 编辑:程序博客网 时间:2024/06/04 22:51

Problem 5. mulfuc

Input file: mulfuc.in
Output file: mulfunc.out
Time limit: 1 second
Memory limit: 256 MB
Mr. Hu 想让大家了解一下积性函数。
积性是函数的一种重要性态,就像单调性、周期性一样。
一个函数f(n) 如果是积性的,当且仅当:
f(nm) = f(n)f(m) (gcd(m; n) = 1)
如果f(n) 是定义在Z+ 上的积性函数,这样定义Z+ 上的g(n):
g(n) =
Σ
djn
f(d)
那么可以证明g(n) 也是一个积性函数。
而在积性函数中,经常使用到以下几个重要的积性函数(容易证明它们都是积性的):
•  (n) 表示正整数n 的正因子个数。
• (n) 表示正整数n 的正因子和。
• (n) 表示正整数n 的Mobius 函数值。
• φ(n) 表示正整数n 的欧拉函数值,即[1; n] 中与n 互质的数的个数。
其中Mobius 函数的定义如下:
(n) =
8><

:
1; n = 1
(��1)r n = p1p2 : : : pr (p1 < p2 <    < pr) pi is prime
0 other cases
现在再定义两个函数:
I(n) =
Σ
djn
(d)
E(n) =
Σ
djn
φ(d)
现在Mr. Hu 需要你去求出上面六个函数在1  n  106 范围内的值。
Input
第1 行包含一个整数opt,表示Mr. Hu 需要你求出的函数的标号。对应关系是:
opt 1 2 3 4 5 6
函数   φ I E
Output
输出1 行,包含opt 对应的函数在[1; 106] 范围内的函数值,两个函数值之间用一个空格隔开。
Sample
mulfuc.in mulfunc.out
1 1 2 2 3 2 4 …
mulfuc.in mulfunc.out
2 1 3 4 7 6 12 …
mulfuc.in mulfunc.out
3 1 -1 -1 0 -1 1 …
mulfuc.in mulfunc.out
4 1 1 2 2 4 2 …
Note
上面的样例输出只给出了前面几项,后面用省略号代替了,你需要输出全部的项。
本题满分100 分,分为6 个测试点,每个测试点100/6 分
• 对于第1 个测试点,opt = 1。
• 对于第2 个测试点,opt = 2。
• 对于第3 个测试点,opt = 3。
• 对于第4 个测试点,opt = 4。
• 对于第5 个测试点,opt = 5。
• 对于第6 个测试点,opt = 6。

#include<iostream>#include<cstdio>using namespace std;const int N = 1000010;bool isnot[N];int pri[N], phi[N], ptot;long long sum[N];void init( int n ) {    isnot[1] = true;    phi[1] = 1;    for( int i = 2; i <= n; i++ ) {        if( !isnot[i] ) {            pri[ptot++] = i;            phi[i] = i - 1;        }         for( int t = 0; t < ptot; t++ ){            int j = pri[t] * i;            if( j > n ) break;            isnot[j] = true;            if( i % pri[t] ) {                phi[j] = phi[pri[t]] * phi[i];            } else {                phi[j] = pri[t] * phi[i];                break;            }        }    }    for( int i = 2; i <= n; i++ )        sum[i] = sum[i-1] + phi[i];}int yin[N];void yinzi( int n ) {    isnot[1] = true;    yin[1] = 1;sum[1] = 1;    for( int i = 2; i <= n; i++ ) {        if( !isnot[i] ) {            pri[ptot++] = i;            yin[i] = 2;sum[i] = i + 1;        }        for( int t = 0; t < ptot; t++ ){            int j = pri[t] * i;            if( j > n ) break;            isnot[j] = true;            if( i % pri[t] == 0 ) {                int b = i, r = 1, a = pri[t];                while( b % pri[t] == 0 ) {                    r++; a *= pri[t]; b /= pri[t];                }                yin[j] = (r + 1) * yin[b];                sum[j] = sum[b];                while( a % pri[t] == 0 ){                    sum[j] += sum[b]*a; a /= pri[t];                }                break;            } else {                yin[j] = yin[pri[t]] * yin[i];                sum[j] = sum[pri[t]] * sum[i];            }        }    }}int mo[N];void mobius( int n ){    isnot[1] = true;    mo[1] = 1;sum[1] = 1;    for( int i = 2; i <= n; i++ ) {        if( !isnot[i] ) {            pri[ptot++] = i;            mo[i] = -1;        }        for( int t = 0; t < ptot; t++ ){            int j = pri[t] * i;            if( j > n ) break;            isnot[j] = true;            if( i % pri[t] ) {                mo[j] = mo[i]*mo[pri[t]];            } else {                mo[j] = 0;                break;            }        }    }    for( int i = 2; i <= n; i++ )        sum[i] = sum[i-1] + mo[i];}int main() {    freopen("mulfunc.in","r",stdin);    freopen("mulfunc.out","w",stdout);    int n;    scanf("%d", &n);    if( n == 4 || n == 6 ){        init(1000000);        if( n == 4 ){            for( register int i = 1; i <= 1000000; i++ )                printf("%d ", phi[i]);            return 0;        } if( n == 6 ){            printf("1 ");            for( register int i = 2; i <= 1000000; i++ )                printf("%d ",i);            return 0;        }    }    if( n == 1 || n == 2 ){        yinzi(1000000);        if( n == 1 ){            for( register int i = 1; i <= 1000000; i++ )                printf("%d ", yin[i]);                return 0;        }else{            for( register int i = 1; i <= 1000000; i++ )                printf("%d ", sum[i]);                return 0;        }    }else{        mobius(1000000);        if( n == 3 ){            for( register int i = 1; i <= 1000000; i++ )                printf("%d ",mo[i]);            return 0;        }else{            printf("1 ");            for( register int i = 2; i <= 1000000; i++ )                printf("0 ");            return 0;        }    }    return 0;}
0 0
原创粉丝点击