2023NOIP A层联测18 新的阶乘

题目大意

我们定义 f ( x ) = x 1 × ( x − 1 ) 2 × ( x − 2 ) 3 × ⋯ × 2 x − 1 × 1 x f(x)=x^1\times (x-1)^2\times (x-2)^3\times \cdots\times 2^{x-1}\times 1^x f(x)=x1×(x1)2×(x2)3××2x1×1x。给定 n n n,求 f ( n ) f(n) f(n)的质因子分解形式。

f ( n ) f(n) f(n)的质因子分解形式,要求按照质因子大小排列,当指数为 1 1 1时应当忽略指数,具体格式要求参见样例。

样例输出

5

样例输出

f(5)=2^8*3^3*5

样例解释

f ( 5 ) = 2 4 × 3 3 × 4 2 × 5 1 = 2 8 × 3 3 × 5 f(5)=2^4\times 3^3\times 4^2\times 5^1=2^8\times 3^3\times 5 f(5)=24×33×42×51=28×33×5

数据范围

1 ≤ n ≤ 1 0 7 1\leq n\leq 10^7 1n107


题解

首先,我们可以用欧拉筛求出 1 0 7 10^7 107以内的质数 p i p_i pi以及,每个数的最小质因数 l t i lt_i lti

我们用 t i t_i ti表示当前每个数未被算入答案的次数,用 c i c_i ci表示每个质数 i i i最终的次数。

我们从大到小枚举 i i i,对于每个 i i i,将 i i i分成 l t i lt_i lti i l t i \dfrac{i}{lt_i} ltii l t i lt_i lti是质数,所以可以将 i i i的次数贡献到 c l t i c_{lt_i} clti中;然后,将 t i l t i t_{\frac{i}{lt_i}} tltii的次数加上 i i i的次数即可。

最后,每个质数 i i i c i c_i ci即为这个质数的次数。

时间复杂度为 O ( n ) O(n) O(n)

code

#include
using namespace std;
const int N=1e7;
int n,fl=0,z[N+5],p[N+5],lt[N+5];
long long ans=0,c[N+5],t[N+5];
void init(){
	for(int i=2;i<=N;i++){
		if(!z[i]){
			p[++p[0]]=i;lt[i]=i;
		}
		for(int j=1;j<=p[0]&&1ll*i*p[j]<=N;j++){
			z[i*p[j]]=1;
			lt[i*p[j]]=p[j];
			if(i%p[j]==0) break;
		}
	}
}
int main()
{
//	freopen("factorial.in","r",stdin);
//	freopen("factorial.out","w",stdout);
	init();
	scanf("%d",&n);
	for(int i=n;i>=2;i--){
		t[i]+=n+1-i;
		c[lt[i]]+=t[i];
		t[i/lt[i]]+=t[i];
		t[i]=0;
	}
	printf("f(%d)=",n);
	for(int i=1;i<=p[0];i++){
		if(c[p[i]]){
			if(fl) printf("*");
			else fl=1;
			if(c[p[i]]==1) printf("%d",p[i]);
			else printf("%d^%lld",p[i],c[p[i]]);
		}
	}
	return 0;
}

你可能感兴趣的:(题解,题解,c++)