51nod1584加权约数和

题目大意:

求:
\[
\sum_{i-1}^n\sum_{j=1}^nmax(i,j)\sigma(i*j)
\]

题解

对于这个\(\max\),套路的把它转化成:
\[
2*\sum_{i=1}^n\sum_{j=1}^ii*\sigma(i*j)-\sum_{i=1}^n i*\sigma(i*i)
\]
对于前面的部分,我们可以:
\[
\sum_{i=1}^{n}\sum_{j=1}^ii\sum_{a|i}\sum_{b|j}a*\frac{j}{b}[(a,b)==1]
\]

\[
\sum_{i=1}^{n}i\sum_{j=i}^n\sum_{a|i}\sum_{b|j}a*\frac{j}{b}\sum_{d|(i,j)}\mu(d)
\]

\[
\sum_{d=1}^n\mu(d)\sum_{i=1}^{\frac{n}{d}}i*d\sum_{a|i}a*d\sum_{j=1}^{i}\sum_{b|j}\frac{j}{b}
\]

\[
\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\frac{n}{d}}i\sum_{a|i}a\sum_{j=1}^i\sum_{b|j}\frac{j}{b}
\]

\[
\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\frac{n}{d}}g_i
\]

\[
\sum_{D=1}^n\sum_{d|D}\mu(d)d^2G_{D/d}
\]

\[
g_n=n*\sigma_n*\sum_{i=1}^n \sigma_i
\]

这个\(g\)数组就可以线性预处理了。

后面的部分可以线性筛,姿势++。

代码

#include<bits/stdc++.h>
#define N 1000009
using namespace std;
typedef long long ll;
const int maxn=1000000;
const int mod=1000000007;
bool vis[N];
int prime[N];
ll mu[N],md[N],mdp[N],ans[N],g[N],sum[N],f[N];
ll sig[N],sig2[N];
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline void prework(int n){
    sig[1]=mu[1]=sig2[1]=md[1]=mdp[1]=1;
    for(int i=2;i<=n;++i){
        //cout<<i<<" "<<md[i]<<" "<<mdp[i]<<endl;
        if(!vis[i]){
            prime[++prime[0]]=i;
            md[i]=mdp[i]=i;
            mu[i]=mod-1;
            sig[i]=i+1;
            sig2[i]=(1ll*i*i%mod+i+1)%mod;
        }
        for(int j=1;j<=prime[0]&&(i*prime[j])<=n;++j){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0){
                mu[i*prime[j]]=0;
                md[i*prime[j]]=prime[j];
                mdp[i*prime[j]]=mdp[i]*prime[j];
                sig[i*prime[j]]=(sig[i]+1ll*prime[j]*mdp[i]%mod*sig[i/mdp[i]]%mod)%mod;
                sig2[i*prime[j]]=sig2[i]+(1ll*mdp[i]*mdp[i]%mod*md[i]%mod+
                1ll*mdp[i]*mdp[i]%mod*md[i]%mod*md[i]%mod)*sig2[i/mdp[i]]%mod;
                sig2[i*prime[j]]%=mod;
                break;
            }
            mu[i*prime[j]]=mod-mu[i];
            sig[i*prime[j]]=sig[i]*sig[prime[j]]%mod;
            md[i*prime[j]]=mdp[i*prime[j]]=prime[j];
            sig2[i*prime[j]]=sig2[i]*sig2[prime[j]]%mod;
        }
    }
    for(int i=1;i<=n;++i)MOD(sum[i]=sum[i-1]+sig[i]);
    for(int i=1;i<=n;++i){
        g[i]=1ll*sig[i]*i%mod*sum[i]%mod;
        MOD(sig2[i]=sig2[i-1]+sig2[i]*i%mod);
        for(int j=i;j<=n;j+=i)MOD(f[j]+=g[i]*mu[j/i]%mod*(j/i)%mod*(j/i)%mod);
        MOD(f[i]+=f[i-1]);
        ans[i]=(f[i]*2-sig2[i]+mod)%mod;
    }
}
int main(){
    prework(maxn);
    int T=rd(),ct=0;
    while(T--){
      int x=rd();ct++;
      printf("Case #%d: %lld\n",ct,ans[x]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ZH-comld/p/11031526.html

时间: 2024-10-25 22:04:21

51nod1584加权约数和的相关文章

[51Nod 1584] 加权约数和

Description 在整理以前的试题时,他发现了这样一道题目:"求 \(\sum\sigma(i)\),其中 \(1≤i≤N\),\(σ(i)\) 表示 \(i\) 的约数之和." 现在他长大了,题目也变难了,所以麻烦你来帮他解决一道数论题吧. 他需要你求如下表达式的值: \[ \sum_{i=1}^N\sum_{j=1}^N\max(i,j)?σ(i?j) \] 其中 \(\max(i,j)\) 表示 \(i\) 和 \(j\) 里的最大值,\(\sigma(i?j)\) 表示

【算法总结】积性函数相关

[线性筛] [模板代码] [线性筛质数] 1 int main() 2 { 3 n=read(); 4 for(int i=2;i<=n;i++) 5 { 6 if(!f[i])pri[++cnt]=i; 7 for(int j=1;j<=cnt;j++) 8 { 9 if(i*pri[j]>n)break; 10 f[i*pri[j]]=1; 11 if(i%pri[j]==0)break; 12 } 13 } 14 } [线性求约数和] 1 void pre() 2 { 3 miu[

浅谈一类积性函数的前缀和(转载)

本文转自:http://blog.csdn.net/skywalkert/article/details/50500009 另外,莫比乌斯反演和杜教筛其他可转到 http://blog.leanote.com/post/totziens/%E8%8E%AB%E6%AF%94%E4%B9%8C%E6%96%AF%E5%8F%8D%E6%BC%94 写在前面 笔者在刷题过程中遇到一些求积性函数前缀和的问题,其中有一类问题需要在低于线性时间复杂度的算法,今天就来浅析一下这类问题的求解方法,当作以后讲课

杜教筛 学习总结

看了看唐老师的blog,照猫画虎的做了几道题目,感觉对杜教筛有些感觉了 但是稍微有一点难度的题目还是做不出来,放假的时候争取都A掉(挖坑ing) 这篇文章以后等我A掉那些题目之后再UPD上去就好啦 由于懒得去写怎么用编辑器写公式,所以公式就准备直接copy唐老师的啦 首先积性函数和完全积性函数什么的就不再多说了 列举常见的积性函数: 1.约数个数函数和约数个数和函数 2.欧拉函数phi 3.莫比乌斯函数mu 4.元函数e 其中e(n)=[n==1] 5.恒等函数I 其中I(n)=1 6.单位函数

bzoj1968【AHOI2005】COMMON 约数研究

1968: [Ahoi2005]COMMON 约数研究 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 1492  Solved: 1139 [Submit][Status][Discuss] Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input 3 Sample Output 5 HINT Source Day2

数学:求一个数的真约数(因数)的个数及所有约数之和

一. 我们知道,每个自然数(不包括0和1)都有2个以上的因数,因数最少的是质数(也叫素数),质数的因数是1和它本身.非质数的自然数也叫合数,它们都含有3个以上(含3个)的因数. 1.怎样求一个数有多少个因数? 对于一个已知的自然数,要求出它有多少个因数,可用下列方法: 首先将这个已知数分解质因数,将此数化成几个质数幂的连乘形式,然后把这些质数的指数分别加一,再相乘,求出来的积就是我们要的结果. 例如:求360有多少个因数. 因为360分解质因数可表示为:360=2^3×3^2×5,2.3.5的指

HDU 5211 筛法求约数

给出n个数a1,a2...an,定义函数 f[i]=j,(i<j),表示aj mod ai=0 的最小j,其中j大于i,如果不存在这样的数,则f[i]=0 求n个数所有f[]值的和 先用筛法o(nlogn)求出每个数的约数 然后每读入一个数x,先找出所有的约数,再看看之前有没有出现过这些约数. 这个回看的过程可以用一个数组维护. 维护watch[],watch[aj]=j 表示aj还没有找到函数值,如果aj是x的约数,那么说明aj的函数值为x的位置. #include<cstdio> #

hdu 4542 数论 + 约数个数相关 腾讯编程马拉松复赛

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4542 小明系列故事--未知剩余系 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 889    Accepted Submission(s): 207 Problem Description "今有物不知其数,三三数之有二,五五数之有三,七七数之有

用numpy计算成交量加权平均价格(VWAP),并实现读写文件

VWAP(Volume-Weighted Average Price,成交量加权平均价格)是一个非常重要的经济学量,它代表着金融资产的“平均”价格.某个价格的成交量越高,该价格所占的权重就越大.VWAP就是以成交量为权重计算出来的加权平均值,常用于算法交易. #!/usr/bin/env python # -*- coding: utf-8 -*- import numpy as np import sys from datetime import datetime i2 = np.eye(2)