【2021 ICPC Gran Premio de Mexico 2da Fecha F】Flipped Factorization 题解

题目大意

  设 x x x 的质因数分解为 p 1 c 1 p 2 c 2 ⋯ p m c m p_1^{c_1}p_2^{c_2}\cdots p_m^{c_m} p1c1p2c2pmcm,记 f ( x ) = c 1 p 1 c 2 p 2 ⋯ c m p m f(x) = c_1^{p_1}c_2^{p_2}\cdots c_m^{p_m} f(x)=c1p1c2p2cmpm,给定 n n n,求 ∑ i = 1 n f ( n )   m o d   1 0 9 + 7 \sum_{i=1}^n f(n) \bmod 10^9+7 i=1nf(n)mod109+7

   n ≤ 1 0 14 n \le 10^{14} n1014
  10s

\\
\\
\\

题解

   n n n 的这个范围没法筛,但却很根号。
  因此用 powerful number 求积性函数和。

  观察到对质数来说 f ( p ) = 1 f(p)=1 f(p)=1,能对上这个形式的,马上想到全 1 函数 1 ( n ) = 1 1(n)=1 1(n)=1。然后观察 h = f 1 = f ∗ μ h = \frac{f}{1} = f * \mu h=1f=fμ,得到
h ( p c ) = { c p − ( c − 1 ) p , c > 1 0 , c = 1 h(p^c)=\begin{cases} c^p-(c-1)^p, &c>1 \\ 0, &c=1 \end{cases} h(pc)={cp(c1)p,0,c>1c=1

  然后推式子
f = h ∗ 1 ⇒ ∑ i = 1 n f ( i ) = ∑ i = 1 n ∑ j = 1 ⌊ n i ⌋ h ( i ) 1 ( j ) = ∑ i = 1 n h ( i ) ⌊ n i ⌋ \begin{aligned} & f = h * 1 \\ \Rightarrow & \sum_{i=1}^n f(i) = \sum_{i=1}^n \sum_{j=1}^{\lfloor \frac ni \rfloor} h(i)1(j) = \sum_{i=1}^n h(i) \lfloor \frac ni \rfloor \\ \end{aligned} f=h1i=1nf(i)=i=1nj=1inh(i)1(j)=i=1nh(i)in

  又由于 h h h 只在 powerful number 处有值,因此用 dfs 把 O ( n ) O(\sqrt n) O(n ) 个 powerful number 都找出来算答案就行了。dfs 的过程中要维护 h h h 的值, c p c^p cp 可以用快速幂算。

代码

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

typedef long long LL;

const int maxp0=1e7+5;
const LL mo=1e9+7;

LL n;

int p[maxp0],p0;
bool bz[maxp0];
void Prime(int n) {
	fo(i,2,n) {
		if (!bz[i]) p[++p0]=i;
		fo(j,1,p0) {
			if (i*p[j]>n) break;
			bz[i*p[j]]=1;
			if (i%p[j]==0) break;
		}
	}
}

LL Pow(LL x,LL y) {
	LL re=1;
	for(; y; y>>=1, x=x*x%mo) if (y&1) re=re*x%mo;
	return re;
}

LL ans;
void dfs(int k,LL h,LL i) {
	if (k>p0) return;
	if (n/i<(LL)p[k]*p[k]) return;
	dfs(k+1,h,i);
	LL last=1;
	i*=p[k];
	for(int c=2; ; c++) {
		LL cur=Pow(c,p[k]);
		LL newh=h*(cur-last+mo)%mo;
		i*=p[k];
		(ans+=(n/i)%mo*newh)%=mo;
		dfs(k+1,newh,i);
		if (n/i<p[k]) break;
		last=cur;
	}
}

int main() {
	Prime(1e7);
	
	scanf("%lld",&n);
	
	ans=n%mo;
	dfs(1,1,1);
	
	printf("%lld\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值