• BZOJ 4176 Lucas的数论 莫比乌斯反演+杜教筛


    题意概述:求,n<=10^9,其中d(n)表示n的约数个数。

    分析:

      首先想要快速计算上面的柿子就要先把d(ij)表示出来,有个神奇的结论:

      

      证明:当且仅当a,b没有相同的质因数的时候我们统计其贡献,可以发现所有被统计的(a,b)乘积的质因数分解形式正好和i,j的所有因数的质因数分解形式一一对应,不重不漏(对于b中质因数指数不为0对应的就是i中指数+b中指数的情况,对于b中质因数指数为0的情况对应i中指数的情况)。

      然后就有如下的推导:

      

      对于这个式子,整个数字分段来算,n/d一共sqrt(n)种取值,用杜教筛求μ的前缀和,后面那部分每次可以用sqrt(n/d)的复杂度计算出来,整个时间复杂度大约是O(n^(3/4))。(实在是太玄学了这个时间复杂度我不是很会算ORZ)

      至于杜教筛......这里我就不讲了吧,看dalao链接!:http://jiruyi910387714.is-programmer.com/posts/195270.html

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<queue>
     8 #include<set>
     9 #include<map>
    10 #include<vector>
    11 #include<cctype>
    12 using namespace std;
    13 const int mo=1000000007;
    14 const int maxn=1000005;
    15 
    16 int N,pri[maxn],mu[maxn],tot;
    17 bool ntp[maxn];
    18 struct Hash{
    19     static const int sz=3000007;
    20     static const int maxn=10000005;
    21     int first[sz],np,next[maxn],id[maxn],val[maxn];
    22     Hash(){
    23         np=0;
    24         memset(first,0,sizeof(first));
    25     }
    26     void ins(int pos,int v){
    27         int i=pos%sz;
    28         next[++np]=first[i],first[i]=np;
    29         id[np]=pos,val[np]=v;
    30     }
    31     int query(int pos){
    32         int i=pos%sz;
    33         for(int p=first[i];p;p=next[p])
    34             if(id[p]==pos) return val[p];
    35         return -1;
    36     }
    37 }hash;
    38 
    39 void get_mu()
    40 {
    41     ntp[0]=ntp[1]=1,mu[1]=1;
    42     for(int i=2;i<=1000000;i++){
    43         if(!ntp[i]) pri[++tot]=i,mu[i]=-1;
    44         for(int j=1;j<=tot&&1ll*pri[j]*i<=1000000;j++){
    45             ntp[i*pri[j]]=1;
    46             if(i%pri[j]==0){ mu[pri[j]*i]=0; break; }
    47             mu[pri[j]*i]=-mu[i];
    48         }
    49     }
    50 }
    51 int F(int n){
    52     int re=0;
    53     for(int i=1,last;i<=n;i=last+1)
    54         last=n/(n/i),re=(re+1ll*(last-i+1)*(n/i)%mo)%mo;
    55     return re;
    56 }
    57 int S(int n){
    58     int re=hash.query(n);
    59     if(re!=-1) return re;
    60     re=1;
    61     for(int i=2,last;i<=n;i=last+1){
    62         last=n/(n/i);
    63         re=(re-1ll*(last-i+1)*S(n/i)%mo+mo)%mo;
    64     }
    65     hash.ins(n,re);
    66     return re;
    67 }
    68 int solve(int n)
    69 {
    70     int re=0,f;
    71     for(int i=1,last;i<=n;i=last+1){
    72         last=n/(n/i),f=F(n/i);
    73         re=(re+1ll*f*f%mo*(S(last)-S(i-1)+mo)%mo)%mo;
    74     }
    75     return re;
    76 }
    77 int main()
    78 {
    79     get_mu();
    80     int sum=0;
    81     for(int i=0;i<=1000000;i++)
    82         hash.ins(i,sum=(sum+mu[i]+mo)%mo);
    83     scanf("%d",&N);
    84     printf("%d
    ",solve(N));
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    版本控制报告
    Beta—review阶段成员贡献分
    规格说明书-----吉林市一日游
    站立会议---11.16
    本周PSP
    软件需求规格说明书
    非序列化字段与反序列化完成后回调
    不同类型的委托变量的共同类型
    实现IDisposable接口的模式
    序列化和反序列化
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8717369.html
Copyright © 2020-2023  润新知