LOJ6053 简单的函数

该文介绍了LOJ6053题目,这是一个关于定义在整数上的特殊函数,涉及到质数、异或运算以及函数的性质。解题策略是利用min25筛,通过变换函数并将其分解为完全积性函数,然后计算模运算后的结果。代码示例展示了如何实现这个算法。
摘要由CSDN通过智能技术生成

LOJ6053 简单的函数

题目大意

有一个函数 f ( x ) f(x) f(x),满足以下性质:

  • f ( 1 ) = 1 f(1)=1 f(1)=1
  • f ( p c ) = p ⊕ c f(p^c)=p \oplus c f(pc)=pc p p p为质数, ⊕ \oplus 表示异或)
  • f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b) a a a b b b互质)

∑ i = 1 n f ( i ) \sum\limits_{i=1}^nf(i) i=1nf(i) ( 1 0 9 + 7 ) (10^9+7) (109+7)取模的结果,其中 1 ≤ n ≤ 1 0 10 1\leq n\leq 10^{10} 1n1010


题解

前置知识:min25筛

观察函数 f ( x ) f(x) f(x) f ( x ) f(x) f(x)在质数和质数的幂的位置比较好求,我们考虑使用min25筛。

x x x为奇质数时, f ( x ) = x ⊕ 1 = x − 1 f(x)=x \oplus 1=x-1 f(x)=x1=x1。当 x x x为偶质数时, f ( x ) = x ⊕ 1 = x + 1 f(x)=x \oplus 1=x+1 f(x)=x1=x+1。令 p ( x ) = x − 1 p(x)=x-1 p(x)=x1,用 p p p函数代替 f f f函数,然后将 p p p函数分为 f 1 ( x ) = x f_1(x)=x f1(x)=x f 2 ( x ) = 1 f_2(x)=1 f2(x)=1两个完全积性函数来求min25筛中的 g g g函数,最后再用 f f f函数的性质来求min25筛中的 S S S函数。对于 p p p f f f x = 2 x=2 x=2处的差,在最后加上即可。

为什么可以这样呢?由函数 S ( n , i ) S(n,i) S(n,i)的递推式, f ( 2 ) f(2) f(2)的值改变只会影响 S S S的递推式中含有 g g g函数的部分。因为答案为 S ( n , 0 ) + 1 S(n,0)+1 S(n,0)+1,而只有 i = 0 i=0 i=0时才会涉及到 f ( 2 ) f(2) f(2)的值( i ≠ 0 i\neq 0 i=0时两个 g g g函数相减将 f ( 2 ) f(2) f(2)的部分抵消了),所以将 f f f改为 p p p在求答案的情况下只会影响一次,也就是答案减少了 f ( 2 ) − g ( 2 ) = 3 − 1 = 2 f(2)-g(2)=3-1=2 f(2)g(2)=31=2,在最后加上即可。

min25筛中函数 S S S的递推式:

S ( n , i ) = g ( n , ∣ p r ( n ) ∣ ) − g ( p r i , ∣ p r ( n ) ∣ ) + ∑ j > i ∑ p r j k ≤ n f ( p r j k ) × ( S ( ⌊ n p r j k ⌋ , j ) + [ k > 1 ] ) S(n,i)=g(n,|pr(n)|)-g(pr_i,|pr(n)|)+\sum\limits_{j>i}\sum\limits_{pr_j^k\leq n}f(pr_j^k)\times (S(\lfloor\dfrac{n}{pr_j^k}\rfloor,j)+[k>1]) S(n,i)=g(n,pr(n))g(pri,pr(n))+j>iprjknf(prjk)×(S(⌊prjkn,j)+[k>1])

code

#include<bits/stdc++.h>
using namespace std;
const int N=200005;
const long long mod=1000000007;
int p1,vt,z[N+5],pr[N+5];
long long n,x,v[N+5],f[2][N+5],s1[N+5],s2[N+5],g1[N+5],g2[N+5];
void dd(){
	for(int i=2;i<=N;i++){
		if(!z[i]){
			pr[++p1]=i;
			s1[p1]=(s1[p1-1]+i)%mod;
			s2[p1]=p1;
		}
		for(int j=1;j<=p1&&i*pr[j]<=N;j++){
			z[i*pr[j]]=1;
			if(i%pr[j]==0) break;
		}
	}
}
void init(){
	x=sqrt(n)+1;
	dd();
	for(long long l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		v[++vt]=n/l;
		if(n/l<=x) f[0][n/l]=vt;
		else f[1][l]=vt;
		long long t=(n/l)%mod;
		g1[vt]=(t*(t+1)/2%mod-1+mod)%mod;
		g2[vt]=(t-1+mod)%mod;
	}
	long long w;
	for(int i=1;i<=p1;i++){
		w=1ll*pr[i]*pr[i];
		long long t;
		for(int j=1;j<=vt&&w<=v[j];j++){
			t=v[j]/pr[i];
			if(t<=x) t=f[0][t];
			else t=f[1][n/t];
			g1[j]=(g1[j]-1ll*pr[i]*(g1[t]-s1[i-1])%mod+mod)%mod;
			g2[j]=(g2[j]-1ll*(g2[t]-s2[i-1])%mod+mod)%mod;
		}
	}
	
}
long long S(long long p,int q){
	if(pr[q]>=p) return 0;
	long long td=(p<=x?f[0][p]:f[1][n/p]);
	long long re=((g1[td]-g2[td]-s1[q]+s2[q])%mod+mod)%mod;
	for(int j=q+1;j<=p1;j++){
		if(1ll*pr[j]*pr[j]>p) break;
		for(long long o=1,pq=pr[j],t;pq<=p;++o,pq=pq*pr[j]){
			t=pq%mod;
			re=(re+1ll*(pr[j]^o)%mod*(S(p/pq,j)%mod+(o>1))%mod)%mod;
		}
	}
	return re;
}
int main()
{
	scanf("%lld",&n);
	init();
	if(n==1) printf("1");
	else printf("%lld\n",(S(n,0)+3)%mod);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值