loj #6053. 简单的函数

#6053. 简单的函数

题目描述

某一天,你发现了一个神奇的函数f(x)f(x)f(x),它满足很多神奇的性质:

  1. f(1)=1f(1)=1f(1)=1。
  2. f(pc)=p⊕cf(p^c)=p \oplus cf(pc​​)=pc(ppp 为质数,⊕\oplus⊕ 表示异或)。
  3. f(ab)=f(a)f(b)f(ab)=f(a)f(b)f(ab)=f(a)f(b)(aaa 与 bbb 互质)。

你看到这个函数之后十分高兴,于是就想要求出 ∑i=1nf(i)\sum\limits_{i=1}^n f(i)i=1n​​f(i)。

由于这个数比较大,你只需要输出 ni=1f(i)mod1000000007。

输入格式

一行一个整数 nnn。

输出格式

一行一个整数 ni=1f(i)mod1000000007。

样例

样例输入 1

6

样例输出 1

16

样例输入 2

233333

样例输出 2

179004642

样例输入3

9876543210

样例输出3

895670833

数据范围与提示

对于30%30\%30%的数据,n≤100n \leq 100n100。
对于60%60\%60%的数据,n≤106n \leq 10^6n106​​。
对于100%100\%100%的数据,1≤n≤10101 \leq n \leq 10^{10}1n1010​​。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000010
#define mod 1000000007
using namespace std;
int p[maxn],cnt,n,f[maxn];
bool vis[maxn];
void prepare(){
    for(int i=2;i<=n;i++){
        if(!vis[i])p[++cnt]=i;
        for(int j=1;j<=cnt&&i*p[j]<=n;j++){
            vis[i*p[j]]=1;
            if(i%p[j]==0)break;
        }
    }
}
void make(int x){
    int a=1,b=1,now=x;
    for(int i=1;i<=cnt;i++){
        if(now==1)break;
        if(now%p[i]==0){
            if(a==1)
                while(now%p[i]==0)a*=p[i],now/=p[i];
            else 
                while(now%p[i]==0)b*=p[i],now/=p[i];
        }
    }
    f[x]=f[a]*f[b];
}
int main(){
    scanf("%d",&n);prepare();
    memset(f,-1,sizeof(f));
    f[1]=1;
    for(int i=1;i<=cnt;i++){
        int t=0;long long mul=1;
        while(1){
            t++;
            mul=mul*(long long)p[i];
            if(mul>1LL*n)break;
            else f[mul]=p[i]^t;
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(f[i]==-1)make(i);
        ans+=f[i];
        if(ans>=mod)ans-=mod;
    }
    printf("%d\n",ans);
    return 0;
}
40分 暴力

 

posted @ 2018-04-29 20:41  Echo宝贝儿  阅读(876)  评论(1编辑  收藏  举报