Luogu P3768 简单的数学题

非常恶心的一道数学题,推式子推到吐血。

光是\(\gcd\)求和我还是会的,但是多了个\(ij\)是什么鬼东西。

\[\sum_{i=1}^n\sum_{j=1}^nij\gcd(i,j)=\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[\gcd(i,j)=d]\]

很套路的把后面的\(d\)提出来:

\[\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[\gcd(i,j)=d]=\sum_{d=1}^nd^3\sum_{i=1}^{\lfloor\frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor\frac{n}{d} \rfloor} ij[\gcd(i,j)=1]\]

利用\(\sum_{d|n}\mu(d)=[n=1]\)替换掉\([\gcd(i,j)=1]\)就有:

\[\sum_{d=1}^nd^3\sum_{i=1}^{\lfloor\frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor\frac{n}{d} \rfloor} ij[\gcd(i,j)=1]=\sum_{d=1}^nd^3\sum_{i=1}^{\lfloor\frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor\frac{n}{d} \rfloor} ij\sum_{x|\gcd(i,j)}\mu(x)\]

然后第一个难点来了,我们把\(x\)弄到前面去枚举,然后利用和式的变换,枚举\(i,j\)是\(x\)的多少倍,然后用分配率凑在一起就有:

\[\sum_{d=1}^nd^3\sum_{i=1}^{\lfloor\frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor\frac{n}{d} \rfloor} ij\sum_{x|\gcd(i,j)}\mu(x)=\sum_{d=1}^nd^3\sum_{x=1}^{\lfloor\frac{n}{d} \rfloor}\mu(x) (\sum_{i=1}^{\lfloor\frac{n}{dx} \rfloor})^2x^2\]

PS:如果上面理解了那么下面就不难了,我们设\(T=dx\)带进去就有:

\[\sum_{d=1}^nd^3\sum_{x=1}^{\lfloor\frac{n}{d} \rfloor}\mu(x) (\sum_{i=1}^{\lfloor\frac{n}{dx} \rfloor})^2x^2=\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2\sum_{d|T}d^3\mu(\frac{T}{d})(\frac{T}{d})^2\]

后面那个东西可以直接提出来就得到:

\[\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2\sum_{d|T}d^3\mu(\frac{T}{d})(\frac{T}{d})^2=\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2\sum_{d|T}dT^2\mu(\frac{T}{d})\]

把\(T^2\)提到前面去:

\[\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2\sum_{d|T}dT^2\mu(\frac{T}{d})=\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2T^2\sum_{d|T}d\mu(\frac{T}{d})\]

后面那个\(\sum_{d|T}d\mu(\frac{T}{d})\)显然就是狄利克雷卷积的形式啊,这就等于\((id\ast\mu)(T)\)

然后回忆一下,\((id\ast\mu)(T)\)不就是\(\phi\)么,因此带进去就有:

\[\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2T^2\sum_{d|T}d\mu(\frac{T}{d})=\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2T^2\phi(T)\]

把\(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i\)用等差数列求和的公式展开就变成:

\[\sum_{T=1}^n(\sum_{i=1}^{\lfloor\frac{n}{T} \rfloor}i)^2T^2\phi(T)=\sum_{T=1}^n(\frac{(1+\lfloor\frac{n}{T} \rfloor)\cdot\lfloor\frac{n}{T} \rfloor}{2})^2T^2\phi(T)\]

如果我们队\(\lfloor\frac{n}{T}\rfloor\)做除法分块,那么现在要求的就是\(T^2\phi(T)\)的前缀和了

考虑用杜教筛的方法化式子,我们社\(f(i)=i^2\phi(i)\),这个时候我们要找一个\(g\)和\(f\)卷起来可以方便求。

由于\(i^2\)很烦,我们考虑先把它消去。令\(g(i)=i^2\),则有:

\(h(n)=(f\ast g)(n)=\sum_{d|n} d^2\phi(d)(\frac{n}{d})^2=n^2\ast(\phi\ast \epsilon)(n)=n^3\)

所以用杜教筛的套路式就是\(g(1)f(n)=h(n)-\sum_{d=2}^ng(d)f(\lfloor\frac{n}{d}\rfloor)\)

即\(f(n)=\sum_{i=1}^ni^3-\sum_{d=2}^ng(d)f(\lfloor\frac{n}{d}\rfloor)\),我们知道\(\sum_{i=1}^ni^3=(\frac{n(n+1)}{2})^2,\sum_{i=1}^ni^2=\frac{n(n+1)(2n+1)}{6}\),所以都可以\(O(1)\)求啦。

CODE

#include<cstdio>
#include<map>
#define RI register int
#define RL register LL
using namespace std;
typedef long long LL;
const int P=10000000;
map <LL,int> sum_f; LL n; int prime[P+5],phi[P+5],cnt,f[P+5],mod,inv2,inv6,ans; bool vis[P+5];
inline void inc(int &x,int y)
{
    if ((x+=y)>=mod) x-=mod;
}
inline void dec(int &x,int y)
{
    if ((x-=y)<0) x+=mod;
}
inline int quick_pow(int x,int p,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline int sum(int x)
{
    return 1LL*x*(x+1)%mod*inv2%mod;
}
inline int sqr(int l,int r)
{
    int t=1LL*r*(r+1)%mod*((r<<1LL)+1)%mod*inv6%mod;
    dec(t,1LL*l*(l-1)%mod*((l<<1LL)-1)%mod*inv6%mod); return t;
}
#define Pi prime[j]
inline void Euler(void)
{
    vis[1]=phi[1]=1; RI i,j; for (i=2;i<=P;++i)
    {
        if (!vis[i]) prime[++cnt]=i,phi[i]=i-1;
        for (j=1;j<=cnt&&i*Pi<=P;++j)
        {
            vis[i*Pi]=1; if (i%Pi) phi[i*Pi]=phi[i]*(Pi-1);
            else { phi[i*Pi]=phi[i]*Pi; break; }
        }
    }
    for (i=1;i<=P;++i) f[i]=f[i-1],inc(f[i],1LL*phi[i]*i%mod*i%mod);
}
#undef Pi
inline int F(LL x)
{
    if (x<=P) return f[x]; if (sum_f.count(x)) return sum_f[x];
    int ans=sum(x%mod); ans=1LL*ans*ans%mod; for (RL l=2,r;l<=x;l=r+1)
    {
        r=x/(x/l);
        int t=sqr(l%mod,r%mod);
        dec(ans,1LL*t*F(x/l)%mod);
    }
    return sum_f[x]=ans;
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    scanf("%d%lld",&mod,&n); Euler(); inv2=quick_pow(2,mod-2);
    inv6=quick_pow(6,mod-2); for (RL l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l); int t=sum(n/l%mod); t=1LL*t*t%mod;
        int Fs=F(r); dec(Fs,F(l-1)); inc(ans,1LL*t*Fs%mod);
    }
    return printf("%d",ans),0;
}

原文地址:https://www.cnblogs.com/cjjsb/p/9965908.html

时间: 2024-07-31 13:03:30

Luogu P3768 简单的数学题的相关文章

P3768 简单的数学题(莫比乌斯反演)

[题目链接] https://www.luogu.org/problemnew/show/P3768 [题目描述] 求 \(\sum_{i=1}^{n}\sum_{j=1}^{n}i* j* gcd(i,j)\mod\ p\) [欧拉反演题解] https://www.luogu.org/blog/zhoutb2333/solution-p3768 /* ----------------------- 最大测试点,时限6s [Input] 1000000007 9786510294 [Outpu

[P3768]简单的数学题

Description: 求出\((\sum_{i=1}^n \sum_{j=1}^n ij\ gcd\ (i,j)) mod\ p\) Hint: \(n<=10^{10}?\) Solution: \(Ans=\sum_{d=1}^nd^3 \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \sum_{j=1}^{\lfloor \frac{n}{d} \rfloor} ij\ \ [gcd(i,j)==1]?\) \(Ans=\sum_{d=1}^nd^3\

P3768 【简单的数学题】

P3768 [简单的数学题] \(Ans=\sum ^{n}_{i=1}\sum ^{n}_{j=1}ijgcd(i,j)\) \(=\sum ^{n}_{i=1}\sum ^{n}_{j=1}ij\sum _{k|i,k|j} φ(k)\) \(=\sum ^{n}_{k=1} φ(k) \sum _{k|i}\sum _{k|j}ij\) \(=\sum ^{n}_{k=1}\varphi (k) k^{2} (\sum ^{n/k}_{i=1}i)^{2}\) \(=\sum ^{n}_{

「洛谷P3768」简单的数学题

题目链接 简单的数学题 题目描述 输入一个整数n和一个整数p,你需要求出 \[\sum_{i=1}^n\sum_{j=1}^n (i\cdot j\cdot gcd(i,j))\ mod\ p\]? 其中\(gcd(a,b)\)表示\(a\)与\(b\)的最大公约数 输入 一行两个整数\(p,n\) 输出 一行一个整数,为题目中所求值 样例 样例输入 998244353 2000 样例输出 883968974 数据范围 \(n\leq 10^{10}\) \(5\times 10^8 \leq

NYOJ 330 一个简单的数学题【数学题】

/* 题目大意:求解1/n; 解题思路:写一个输出小数的算法 关键点:如何处理小数点循环输出 解题人:lingnichong 解题时间:2014-10-18 09:04:22 解题体会:输出小数的算法还没完全理解,先记着 */ 一个简单的数学题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 zyc最近迷上了数学,一天,dj想出了一道数学题来难住他.算出1/n,但zyc一时答不上来希望大家能编程帮助他. 输入 第一行整数T,表示测试组数.后面T行,每行一个整数 n

一个就简单的数学题 NYOJ 330

1 #include<stdio.h>//一个就简单的数学题(330) 2 #include<string.h> 3 int a[100010]; 4 int main() 5 { 6 int x,m,yu; 7 scanf("%d",&x); 8 while(x--){ 9 scanf("%d",&m); 10 memset(a,0,sizeof(a)); 11 yu=1; 12 if(m>0)printf("

NYOJ 330 一个简单的数学题

一个简单的数学题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 zyc最近迷上了数学,一天,dj想出了一道数学题来难住他.算出1/n,但zyc一时答不上来希望大家能编程帮助他. 输入 第一行整数T,表示测试组数.后面T行,每行一个整数 n (1<=|n|<=10^5). 输出 输出1/n. (是循环小数的,只输出第一个循环节). 样例输入 4 2 3 7 168 样例输出 0.5 0.3 0.142857 0.005952380 直接模拟求余数的方法,用一个数组

leetcode_118题——Pascal&#39;s Triangle(简单的数学题)

Pascal's Triangle Total Accepted: 43845 Total Submissions: 145271My Submissions Question Solution Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] Hi

【Luogu3768】简单的数学题(莫比乌斯反演,杜教筛)

[Luogu3768]简单的数学题(莫比乌斯反演,杜教筛) 题面 洛谷 \[求\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)\] $ n<=10^9$ 题解 很明显的把\(gcd\)提出来 \[\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[gcd(i,j)==d]\] 习惯性的提出来 \[\sum_{d=1}^nd^3\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}ij[gcd(i,j)==1]\] 后面这玩意很明显的来一发