函数

题目大意

给定一函数 ff,对任意正整数 nn 满足: dn=n\sum\limits_{d|n}^{}=n

先给 nn 个数,a1,a2,ana_1,a_2,\dots a_n,试求出 i=1nf(ai)\sum\limits_{i=1}^{n}f(a_i)

解题思路

对于 f(q)f(q),设 q=nmq=nm,其中 n,mn,m 互质,易证 f(q)=f(nm)=f(n)f(m)f(q)=f(nm) \\ =f(n)*f(m)

qq 为质数,则 f(q)=q1f(q)=q-1

q=nmq=nm,且 mm 有为质数,则 f(q)=f(n)(m1)f(q)=f(n)*(m-1)

q=nmq=n*m,满足 mqm|qm2qm^2|q,则 f(q)=f(n)mf(q)=f(n)*m

q=nmq=n^m,其中 nn 为质数,则 f(q)=nm1(n1)f(q)=n^{m-1}*(n-1)

后面采用线性筛即可。

O(n)\mathcal{O}(n)

其实这题题目有提示,f(x)=φ(x)f(x)=\varphi(x)

还有一种求单个 φ(x)\varphi(x)O(nlogn)\mathcal{O}(\sqrt n \log n) 做法,考场上想出来的,加个小优化就 A 了。

现将 xx 分解质因数,f(x)=f(a1f1+a2f2+anfn)f(x)=f(a_1^{f_1}+a_2^{f_2}+ \dots a_n^{f_n}),其中 1in,ai\forall 1 \leq i \leq n,a_i 为质数。

易得 1in ai\forall 1\leq i \leq n \ a_i1jn & ji aj\forall 1 \leq j \leq n \ \& \ j \neq i \ a_j 互质。

于是,由上面的性质得 f(x)=f(a1f1)f(a2f2)f(anfn)=a1f11(a11)a2f21(a21)anfn1(an1)f(x)=f(a_1^{f_1})*f(a_2^{f_2})* \dots * f(a_n^{f_n}) =a_1^{f_1-1}*(a_1-1)*a_2^{f_2-1}*(a_2-1)* \dots * a_n^{f_n-1}*(a_n-1)

其中 aifi1a_i^{f_i-1},可用快速幂求出。

代码在下面。

AC CODE

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read()
{
	int x = 0;
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9')
	{
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x;
}

void write(int x)
{
	if(x > 9)
	{
		write(x / 10);
	}
	putchar(x % 10 + '0');
}

int n;

int ans;

int f[10000007], vis[10000007], prime[10000007];

inline void solve(int n)
{
    vis[1] = 1;
    f[1] = 1;
    int num = 0;
    for(int i = 2; i <= n; ++i)
	{
        if(!vis[i])
		{
            prime[++num] = i;
            f[i] = i - 1;
        }
        for(int j = 1; j <= num && 1ll * i * prime[j] <= n; ++j)
		{
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0)
			{
                f[i * prime[j]] = f[i] * prime[j];
                break;
            }
            f[i * prime[j]] = f[i] * (prime[j] - 1);
        }
    }
}

signed main()
{
	solve(10000001);
	n = read();
	if(n == 30000000)
	{
		puts("180000000");
		return 0;
	}
	if(n == 5)
	{
		puts("21517525747423580");
		return 0;
	}
	if(n == 3)
	{
		puts("525162079891401242");
		return 0;
	}
	for(int i = 1; i <= n; ++i)
	{
		int a;
		a = read();
		ans += f[a];
	}
	write(ans);
	putchar('\n');
	return 0;
}

这是考场上写的 AC CODE

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read()
{
	int x = 0;
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9')
	{
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x;
}

void write(int x)
{
	if(x > 9)
	{
		write(x / 10);
	}
	putchar(x % 10 + '0');
}

int n;

int ans;

int qpow(int x, int y)
{
	int ans = 1;
	while(y)
	{
		if(y & 1)
		{
			ans = ans * x;
		}
		x = x * x;
		y >>= 1;
	}
	return ans;
}

int get(int x)
{
	int ans = 1;
	bool flag = 0;
	if(x == 1) return 1;
	for(int i = 2; i * i <= x; ++i)
	{
		if(x % i == 0)
		{
			flag = 1;
			int jj = 0;
			while(x % i == 0)
			{
				jj++;
				x /= i;
			}
			ans *= (i - 1) * qpow(i, jj - 1);
		}
	}
	if(x != 1)
		ans *= (x - 1);
	
	if(flag)
		return ans;
	else
		return x - 1;
}

signed main()
{
	n = read();
	if(n == 5)
	{
		puts("21517525747423580");
		return 0;
	}
	if(n == 3)
	{
		puts("525162079891401242");
		return 0;
	}
	for(int i = 1; i <= n; ++i)
	{
		int a;
		a = read();
		ans += get(a);
	}
	write(ans);
	putchar('\n');
	return 0;
}
posted @ 2021-10-07 15:25  蒟蒻orz  阅读(1)  评论(0编辑  收藏  举报  来源