bzoj 4176 Lucas的数论

bzoj 4176 Lucas的数论

  • 和约数个数和那题差不多.只不过那个题是多组询问,这题只询问一次,并且 \(n\) 开到了 \(10^9\).
    \[
    \begin{align*}
    \sum_{i=1}^N \sum_{j=1}^N f(ij)&=
    \sum_{i=1}^N \sum_{j=1}^N \sum_{x|i} \sum_{y|j}[gcd(x,y)=1]\\&=
    \sum_{i=1}^N \sum_{j=1}^N \sum_{x|i} \sum_{y|j} \sum_{d|gcd(x,y)}\mu(d)\\&=
    \sum_{d=1}^N \mu(d)\sum_{x=1}^{\lfloor \frac N d \rfloor} \sum_{y=1}^{\lfloor \frac M d \rfloor}\lfloor \frac {N}{dx} \rfloor \lfloor \frac {N}{dy} \rfloor\\&=
    \sum_{d=1}^N \mu(d)\cdot \sum_{x=1}^{\lfloor \frac N d \rfloor}\lfloor \frac {N}{dx} \rfloor\cdot \sum_{y=1}^{\lfloor \frac N d \rfloor}\lfloor \frac {N}{dy} \rfloor.
    \end{align*}
    \]
  • 记 \(f'(n)=\sum_{i=1}^n \lfloor \frac n i \rfloor\).
  • 则答案为

\[
\sum_{d=1}^N \mu(d) \cdot f'(\lfloor\frac N d\rfloor)\cdot f'(\lfloor \frac N d \rfloor).
\]

  • \(N\) 是 \(10^9\) 级别,所以用杜教筛求 \(\mu\) 的前缀和.然后套两个整除分块,外层算答案,里层算 \(f'\) 即可.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        fh=-1,jp=getchar();
    while (jp>='0'&&jp<='9')
        out=out*10+jp-'0',jp=getchar();
    return out*fh;
}
const int P=1e9+7;
const int inv2=(P+1)>>1;
inline int add(int a,int b)
{
    return (a + b) % P;
}
inline int mul(int a,int b)
{
    return 1LL * a * b % P;
}
inline int sub(int a,int b)
{
    return add(a,P-b);
}
const int MAXN=3e6+10;
int n,ans=0;
int f[MAXN],prime[MAXN],cnt=0,mu[MAXN],ism[MAXN],summu[MAXN];
int calc_F(int i)
{
    int res = 0;
    for(int l=1,r; l<=i; l=r+1)
    {
        r = i/(i/l);
        res = add(res,mul(r-l+1,(i/l)));
    }
    return res;
}
void init(int N)
{
    ism[1] = 1;
    mu[1] = 1;
    for(int i=2; i<=N; ++i)
    {
        if(!ism[i])
        {
            prime[++cnt] = i;
            mu[i] = -1;
        }
        for(int j=1; j<=cnt; ++j)
        {
            ll num = i * prime[j];
            if(num > N)
                break;
            ism[num] = 1;
            if(i % prime[j] == 0)
                break;
            else
                mu[num] = -mu[i];
        }
    }
    for(int i=1; i<=N; ++i)
        summu[i] = add(summu[i-1],P+mu[i]);
}
int AP(int x)
{
    return mul(mul(x,x+1),inv2);
}
map<int,int> mp;
const int sqN=31200;
int calc(int x)
{
    if(x<=sqN)
        return summu[x];
    if(mp.find(x)!=mp.end())
        return mp[x];
    int res=1;
    for(int l=2,r;l<=x;l=r+1)
    {
        r=x/(x/l);
        int tmp=mul(r-l+1,calc(x/l));
        res=add(res,P-tmp);
    }
    return mp[x]=res;
}
void solve()
{
    init(sqN);
    for(int l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        int tmp=add(calc(r),P-calc(l-1));
        tmp=mul(tmp,mul(calc_F(n/l),calc_F(n/l)));
        ans=add(tmp,ans);
    }
    cout<<ans<<endl;
}
int main()
{
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
    n=read();
    solve();
    return 0;
}

原文地址:https://www.cnblogs.com/jklover/p/10659260.html

时间: 2024-10-08 18:24:41

bzoj 4176 Lucas的数论的相关文章

●BZOJ 4176 Lucas的数论

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4176 题解: 莫比乌斯反演,杜教筛 首先有这么一个结论: 令d(n)表示n的约数的个数(就是题目中的f(n)),则有 $$d(nm)=\sum_{i|n}\sum_{j|m}[gcd(i,j)==1]$$ ●BZOJ 3994 [SDOI2015]约数个数和也用到了这个东西. 那么就下来接直接进行求ANS的式子的推导: $$\begin{aligned}ANS&=\sum_{n=1}^{N

BZOJ 4176 Lucas的数论 莫比乌斯反演

题目大意:给定n(n≤109),求∑ni=1∑nj=1d(ij) 推错式子害死人... 由d|ij等价于dgcd(i,d)|j可得 ∑ni=1∑nj=1d(ij) =∑ni=1∑n2d=1?n?gcd(i,d)d? =∑nd=1∑?nd?i=1∑?n2d?j=1?nj?[gcd(i,j)=1] =∑nd=1∑?nd?i=1∑nj=1?nj?[gcd(i,j)=1] =∑nd=1∑?nd?i=1∑nj=1?nj?∑k|i,k|jμ(k) =∑nk=1μ(k)(∑?nk?d=1?nkd?)2 O(n

【bzoj 4176】 Lucas的数论 莫比乌斯反演(杜教筛)

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Output 8 HINT 对于100%的数据n <= 10^9. 题解: 解锁新技能:杜教筛. 再复习一下: 若$F(n)=\s

BZOJ 1406 [AHOI2007]密码箱 数论

题意:链接 方法:数论 解析: 对于这道题,假设n=a*b;然后b是较大的因子 之后怎么来想呢? 之后就是根号找因子,找到每个a,b,之后从0~n枚举b的倍数. 因为x2?1=0(mod n) 所以(x?1)?(x+1)=0(mod n) 因为我们枚举的数就是k1*b,所以我们只要讨论一下,k1*b是等于x-1还是x+1就好了,之后就是判断下边界什么的就把所有的可能值加到一个set里!千万不要犯傻加到map里!!千万不要!!不要认为map啥都能干!! 之后因为set内元素的唯一性.直接输出内部所

【bzoj4176】Lucas的数论 莫比乌斯反演+杜教筛

题目描述 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 其中f(ij)表示ij的约数个数. 他发现答案有点大,只需要输出模1000000007的值. 输入 第一行一个整数n. 输出 一行一个整数ans,表示答案模1000000007的值. 样例输入 2 样例输出 8 题解 莫比乌斯反演+杜教筛 首先有个神奇

Bzoj4176 Lucas的数论

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 其中 表示ij的约数个数. 他发现答案有点大,只需要输出模1000000007的值. Input 第一行一个整数n. Output 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Ou

数论专项测试——约数个数和(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[ma

【BZOJ4176】 Lucas的数论

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 其中 表示ij的约数个数. 他发现答案有点大,只需要输出模1000000007的值. Input 第一行一个整数n. Output 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Ou

BZOJ 1407: [Noi2002]Savage( 数论 )

枚举答案, 然后O(N^2)枚举野人去判他们是否会在有生之年存在同山洞. 具体做法就是: 设第x年相遇, 则 Ci+x*Pi=Cj+x*Pj (mod M), 然后解同余方程. 复杂度应该是O(ans*N^2log(ans)), 但是实际远小于....能够AC -------------------------------------------------------------------- #include<cstdio> #include<algorithm> #inclu