[LOJ#6053] Strange function

Description

Given a function f(x) that satisfies:
f(1)=1,
f(p^c)=p xor c, p is prime
f(ab)=f(a)*f(b),(a,b )=1
to find ni=1f(i) modulo 1e9+7
n<=1e10

Solution

min_25 sieve
example problem, you can look at the blog of the god zzq.
We only need to know the sum of f(x) of all prime numbers. Obviously, the exponent is 1, so we can directly use the sum of prime numbers - the number of prime numbers.
Note that 2 is the only even prime number, just judge it at random.

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

typedef long long ll;

const int N=2e5+5,Mo=1e9+7;

int pwr(int x,int y) {
    int z=1;
    for(;y;y>>=1,x=(ll)x*x%Mo)
        if (y&1) z=(ll)z*x%Mo;
    return z;
}

int p[N],g[N],h[N],s[N],id1[N],id2[N],m,inv2,tot,cnt;
bool bz[N];
ll n,w[N];

void get_prime(int n) {
    fo(i,2,n) {
        if (!bz[i]) p[++tot]=i;
        fo(j,1,tot) {
            int k=i*p[j];if (k>n) break;
            bz[k]=1;if (!(i%p[j])) break;
        }
    }
}

int ID(ll x) {return x<=m?id1[x]:id2[n/x];}

int F(ll x,int j) {
    if (x<=1||p[j]>x) return 0;
    int k=ID(x),ans=(g[k]-s[j-1]-(h[k]-(j-1)))%Mo;
    if (j==1) ans+=2;
    fo(i,j,tot) {
        if ((ll)p[i]*p[i]>x) break;
        ll t1=p[i],t2=(ll)p[i]*p[i];
        for(int e=1;t2<=x;t1=t2,t2=t1*p[i],e++)
            (ans+=(ll)F(x/t1,i+1)*(p[i]^e)%Mo+(p[i]^(e+1)))%=Mo;
    }
    return ans;
}

int main() {
    scanf("%lld",&n);
    m=sqrt(n);get_prime(m);
    inv2=pwr(2,Mo-2);
    for(ll l=1,r=0;l<=n;l=r+1) {
        r=n/(n/l);
        w[++cnt]=n/l;
        int res=w[cnt]%Mo;
        g[cnt]=(ll)res*(res+1)%Mo*inv2%Mo;g[cnt]--;
        h[cnt]=(w[cnt]-1)%Mo;
        if (w[cnt]<=m) id1[w[cnt]]=cnt;
        else id2[n/w[cnt]]=cnt;
    }
    fo(i,1,tot) s[i]=(s[i-1]+p[i])%Mo;
    fo(j,1,tot) 
        fo(i,1,cnt) {
            if ((ll)p[j]*p[j]>w[i]) break;
            int k=ID(w[i]/p[j]);
            (g[i]-=(ll)p[j]*(g[k]-s[j-1])%Mo)%=Mo;(g[i]+=Mo)%=Mo;
            (h[i]-=h[k]-(j-1))%=Mo;(h[i]+=Mo)%=Mo;
        }
    printf("%d\n",F(n,1)+1);
    return 0;   
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324810302&siteId=291194637