线性逆元
inv[1]=1;
for(int i=2;i<=n;++i){
inv[i]=prd((P-P/i),inv[P%i]);
}
线性筛
点击查看代码
void A(int& x,int y){
x+=y;
if(x>=P) x-=P;
}
int u[N],s[N],pri[N];
bool vis[N];
vector<int>d[N];
void init(){
int n=100000,tot=0;
u[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){
pri[++tot]=i;
u[i]=P-1;
}
for(int j=1;j<=tot && pri[j]*i<=n;j++){
int x=pri[j]*i;
vis[x]=1;
if(!(i%pri[j])){
u[x]=0;
break;
}
u[x]=P-u[i];
}
}
for(int i=1;i<=n;i++){
A(s[i],u[i]);
d[i].push_back(i);
for(int j=2;i*j<=n;j++){
A(s[i*j],1ll*u[i]*j%P);
d[i*j].push_back(i);
}
}
}
min-25筛求质数+数论分块
点击查看代码
using namespace std;
const int N = 1000010,P=1e9+7;
int prime[N], id1[N], id2[N], flag[N], ncnt, m;
ll g[N], sum[N], a[N], T;
ll n;
int ID(ll x){
return x <= T ? id1[x] : id2[n / x];
}
ll calc(ll x){
return (x%P * ( (x + 1)%P ) %P*((P+1)/2)%P +P- 1)%P;
}
ll f(ll x){
return x;
}
void init(ll n){
T = sqrt(n + 0.5);
for(int i = 2; i <= T; i ++){
if(!flag[i]) prime[++ncnt] = i, sum[ncnt] = sum[ncnt - 1] + i;
for(int j = 1;j <= ncnt && i * prime[j] <= T; j ++){
flag[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
for(ll l = 1; l <= n; l = n / (n / l) + 1){
a[++m] = n / l;
if(a[m] <= T) id1[a[m]] = m; else id2[n / a[m]] = m;
g[m] = calc(a[m]);
}
for(int i = 1; i <= ncnt; i ++){
for(int j = 1; j <= m && (ll)prime[i] * prime[i] <= a[j]; j ++){
g[j] = (g[j] +P- (ll)prime[i] * (g[ID(a[j] / prime[i])] - sum[i - 1]+P)%P)%P;
}
}
}
ll solve(ll x){
if(x <= 1) return 0;
memset(g,0,sizeof(g));
memset(id1,0,sizeof(id1));
memset(id2,0,sizeof(id2));
memset(flag,0,sizeof(flag));
memset(prime,0,sizeof(prime));
memset(sum,0,sizeof(sum));
memset(a,0,sizeof(a));
m=ncnt=0;
return n = x, init(n), g[ID(n)]%P;
}
ll nn,p[N],s[N],ans;
int main(){
cin>>nn;
solve(nn);
//puts("!");
for(int i=1;i<=ncnt;i++){
//cout<<"pri="<<prime[i]<<endl;
int t=0;
p[0]=1;
while(p[t]<=nn/prime[i]) t++,p[t]=p[t-1]*prime[i];
//cout<<"t="<<t<<endl;
for(int i=0;i<=t;i++) s[i]=nn/p[i]%P;
for(int i=0;i<t;i++) (s[i]+=P-s[i+1])%=P;//cout<<s[i]<<" "; puts("");
for(int y=2;y<=t;y++){
for(int x=0;x<y;x++){
(ans+=1ll*(prime[i]%P)*(y-max(x,1))%P*s[x]%P*s[y]%P)%=P;
}
}
}
//cout<<"ans="<<ans<<endl;
for(ll i=1;i<=nn;){
ll x=nn/i,j=nn/x;
//cout<<i<<" "<<j<<" "<<x<<endl;
(ans+=1ll*((g[ID(j)]%P)+P-(g[ID(i-1)]%P))*(x%P)%P*((nn-x)%P)%P)%=P;
i=j+1;
//cout<<"ans="<<ans<<endl;
}
ans=(ans%P+P)%P;
cout<<(ans+ans)%P<<endl;
}
PN筛
题目链接
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const ll P=(1ll<<57)*29+1,V2=(P+1)/2;
ll mul(ll a,ll x){
return ((__int128)a)*x%P;
}
ll fpw(ll a,ll x){
ll s=1;
for(;x;x>>=1,a=mul(a,a)) if(x&1) s=mul(s,a);
return s;
}
void mod(ll& x){
x=(x%P+P)%P;
}
ll sum(ll n){
return mul(mul(n,n+1),V2);
}
ll iv[N],sv[N],pr[N],pt,ans,n;
bool vs[N];
void dfs(int k,ll c,ll s){
if(k>pt || pr[k]>n/c/pr[k]){
(ans+=mul(c,mul(s,sum(n/c))))%=P;
return;
}
ll t=c;
dfs(k+1,t,s);
for(int i=1;;i++){
if(pr[k]>n/t) break;
t*=pr[k];
if(i>=2) dfs(k+1,t,P-mul(s,sv[i]));
}
}
void work(){
cin>>n;
ans=0;
dfs(1,1,1);
cout<<mul(ans,fpw(n,P-2))<<endl;
}
int main()
{
int n=1e6;
iv[1]=1;
for(int i=2;i<=n;++i){
iv[i]=mul((P-P/i),iv[P%i]);
sv[i]=mul(iv[i],iv[i-1]);
}
for(int i=2;i<=n;i++){
if(!vs[i]) pr[++pt]=i;
for(int j=1;j<=pt && pr[j]<=n/i;j++){
int x=i*pr[j];
vs[x]=1;
if(!(i%pr[j])){
break;
}
}
}
int T; cin>>T; while(T--) work();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】