zoukankan      html  css  js  c++  java
  • 数论专项测试——约数个数和(lucas的数论)

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 using namespace std;
     7 typedef long long int64;
     8 const int mod=1000000007;
     9 #define maxn 2000005
    10 int top,tot,d[maxn],prim[maxn],mu[maxn];
    11 bool vis[maxn];
    12 int64 n,f[maxn],ans;
    13 void prepare(){
    14     tot=top=0,memset(vis,1,sizeof(vis)),mu[0]=0,mu[1]=1,f[1]=1;
    15     for (int i=2;i<maxn;i++){
    16         if (vis[i]==1){
    17             prim[++top]=i;
    18             d[i]=i;
    19             mu[i]=-1;
    20             f[i]=2;
    21         }
    22         for (int j=1;j<=top;j++){
    23             if (i*prim[j]>=maxn) break;
    24             vis[i*prim[j]]=0;
    25             if (i%prim[j]==0){
    26                 d[i*prim[j]]=d[i]*prim[j];
    27                 mu[i*prim[j]]=0;
    28                 f[i*prim[j]]=f[i/d[i]]*(f[d[i]]+1);
    29                 break;
    30             }else{
    31                 d[i*prim[j]]=prim[j];
    32                 mu[i*prim[j]]=mu[i]*mu[prim[j]];
    33                 f[i*prim[j]]=f[i]*f[prim[j]];
    34             }
    35         }
    36     }
    37     for (int i=2;i<maxn;i++) mu[i]+=mu[i-1];
    38     for (int i=2;i<maxn;i++) f[i]=(f[i-1]+f[i])%mod;
    39 }
    40 #define maxp 100007
    41 #define maxm 4000005
    42 int now[maxp],prep[maxm];
    43 int64 val[maxm],id[maxm];
    44 void insert(int x,int64 y){
    45     int pos=x%maxp;
    46     prep[++tot]=now[pos],now[pos]=tot,val[tot]=y,id[tot]=x;
    47 }
    48 int64 find(int x){
    49     int pos=x%maxp;
    50     for (int i=now[pos];i;i=prep[i]){
    51         if (id[i]==x) return val[i];
    52     }
    53     return -1;
    54 }
    55 int64 Mu(int x){
    56     if (x<maxn) return mu[x];
    57     int64 temp=find(x),t;
    58     if (temp!=-1) return temp;
    59     temp=1;
    60     for (int j,i=2;i<=x;i=j+1){
    61         j=x/(x/i);  t=Mu(x/i);
    62         temp=((temp-1LL*(j-i+1)*t%mod)%mod+mod)%mod;
    63     }
    64     insert(x,temp); return temp;
    65 }
    66 int64 F(int x){
    67     if (x<maxn) return f[x];
    68     int64 temp=0;
    69     for (int j,i=1;i<=x;i=j+1){
    70         j=x/(x/i);
    71         temp=(temp+1LL*(x/i)*(j-i+1)%mod)%mod;
    72     }
    73     return temp%mod;
    74 }
    75 int main(){
    76     int64 temp;
    77     prepare();
    78     scanf("%lld",&n);
    79     ans=0;
    80     for (int j,i=1;i<=n;i=j+1){
    81         j=n/(n/i); temp=F(n/i);
    82         ans=(ans+1LL*(Mu(j)-Mu(i-1))%mod*temp%mod*temp%mod)%mod;
    83     }
    84     printf("%lld
    ",(ans%mod+mod)%mod);
    85     return 0;
    86 }
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4176

    题目大意:

     答案对10^9+7取模。  1<=n<=10^9,单组询问。

    吐槽:这是一个对我来说启发很大的题,加深了我对杜教筛的理解。

    做法:式子不好写,还是用图好了。

    然后用莫比乌斯反演继续化简:

     

    这样就好办了,floor(n/k)最多只有O(sqrt(n))级别的取值,维护mu的前缀和?没错,既然不能预处理,那我们就杜教筛,F数组呢,没错,F[i]=sigam(i/j),1<=j<=i,可以sqrt(n)级别的复杂度做出,如果我们尽可能多的预处理出mu和F,那么可以把总复杂度降至O(n^(2/3)),足以过此题。

  • 相关阅读:
    ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)
    ●SPOJ 1811 Longest Common Substring
    ●POJ 1509 Glass Beads
    ●BZOJ 4556 [Tjoi2016&Heoi2016]字符串
    ●BOZJ 2229 [Zjoi2011]最小割
    ●BOZJ 4456 [Zjoi2016]旅行者
    ●观光(17.12.02多校联测题目)
    ●BZOJ 2007 NOI 2010 海拔
    mysql--->B+tree索引的设计原理
    mysql--->权限管理原理和设置
  • 原文地址:https://www.cnblogs.com/OYzx/p/5778390.html
Copyright © 2011-2022 走看看