[LOJ6053][min_25]简单的函数

LOJ6053

对于一个质数 p p p,除非它等于2,否则 p x o r 1 = p − 1 p xor 1=p-1 pxor1=p1
所以算一下 f = 1 f=1 f=1 s = p s=p s=p,相减即可
然后就变成min_25模板了?
Code:

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define inv2 500000004
using namespace std;
inline ll read(){
	ll res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f; 
}
inline int add(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dec(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
 
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void Dec(int &x,int y){x-=y;if(x<0) x+=mod;}
inline void Mul(int &x,int y){x=1ll*x*y%mod;}

inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) res=mul(res,a);return res;}

inline int sum(ll x){return mul(x%mod,mul((x+1)%mod,inv2));}

const int N=1e6+5;

int f1[N],f2[N],s1[N],s2[N],pri[N];
int tot=0;
inline void init(ll n){
	if(n<=1) return;
	int k=sqrt(n);
	for(int i=1;i<=k;i++) f1[i]=i-1,f2[i]=(n/i-1)%mod,s1[i]=dec(sum(i),1),s2[i]=dec(sum(n/i),1);
	for(int i=2;i<=k;i++){
		if(f1[i]==f1[i-1]) continue;
		pri[++tot]=i;
		for(int j=1;j<=k/i;j++) Dec(f2[j],dec(f2[j*i],f1[i-1])),Dec(s2[j],mul(i,dec(s2[j*i],s1[i-1])));
		for(int j=k/i+1;1ll*j*i*i<=n && j<=k;j++) Dec(f2[j],dec(f1[n/j/i],f1[i-1])),Dec(s2[j],mul(i,dec(s1[n/j/i],s1[i-1])));
		for(int j=k;j>=1ll*i*i;j--) Dec(f1[j],dec(f1[j/i],f1[i-1])),Dec(s1[j],mul(i,dec(s1[j/i],s1[i-1])));
		
	}
	for(int i=1;i<=k;i++){
		Dec(s1[i],f1[i]);inc(s1[i],mul(2,i>=2));
		Dec(s2[i],f2[i]);inc(s2[i],mul(2,(n/i)>=2ll));
	}
}
ll n;
int ans=1;
void calc(int cnt,int coef,int lim,ll res){
	int g=(res<=lim?s1[res]:s2[n/res]);
	inc(ans,mul(coef,dec(g,s1[pri[cnt-1]])));
	for(int i=cnt;i<=tot;i++){
		if(1ll*pri[i]*pri[i]>res) return;
		for(ll now=pri[i],k=1;now<=res;k++){
			if(now*pri[i]<=res) calc(i+1,mul(coef,pri[i]^k),lim,res/now);
			if(k>=2) inc(ans,mul(coef,pri[i]^k));
			now=now*pri[i];
		}
	}
}
int main(){
	n=read();
	init(n);
	calc(1,1,sqrt(n),n);
	cout<<ans<<"\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值