题目大意:

  求$\sum\limits_{i=1}^n\sum\limits_{j=1}^n[lcm(i,j)>n](n\leq 10^{10})$的值。

题解:

  这题貌似有n多种做法...

  为了更好统计,把原式变为$n^2-\sum\limits_{i=1}^n\sum\limits_{j=1}^n[lcm(i,j)\leq n]$。

  然后开始毒瘤...

  首先,考虑枚举$lcm(i,j)$,设为$d$,计算有多少对$i.j$的最小公倍数为$d$。

  设$i=p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}$,$tp(i)=k$

  再枚举$gcd(i,j)$,设为$x$,又由于$\frac{i}{gcd(i,j)}$和$\frac{j}{gcd(i,j)}$互质,那么要统计的就是把$\frac{d}{x}$拆成两个互质数的方案数。

  那么简单想一下,方案数就是$2^{tp(\frac{d}{x})}$,因为同一个质因子不能同时出现在两个数中。

  于是答案变为:

    $\sum\limits_{d=1}^n\sum\limits_{x|d}2^{tp(x)}$

  枚举$x$,即$\sum\limits_{x=1}^n2^{tp(x)}\lfloor\frac{n}{x}\rfloor$。

  然后我们发现$\lfloor\frac{n}{x}\rfloor$可以进行数论分块,所以需要求出$2^{tp(x)}$的前$n$项和。

  但是...我不会啊!!

  所以接下来我开始打表,然后我惊奇地发现:

    $2^{tp(x)}=\sum\limits_{t|x}\mu^2(t)$!!!(别问我是怎么发现的)

  带入原式,得:$\sum\limits_{x=1}^n\lfloor\frac{n}{x}\rfloor\sum\limits_{t|x}\mu^2(t)$

  反手枚举$t$,即$\sum\limits_{t=1}^n\mu^2(t)\sum\limits_{x=1}^{n/t}\lfloor\frac{n}{tx}\rfloor$

  另外,$\sum\limits_{i=1}^nd(i)=\sum\limits_{i=1}^n\lfloor\frac{n}{i}\rfloor$,其中$d(i)$表示$i$的约数个数。

  因此答案为:$\sum\limits_{t=1}^n\mu^2(t)\sum\limits_{x=1}^{n/t}d(x)$

  式子结束了,需要调用两层数论分块,还有要预处理出$\mu^2(t)$以及$d(x)$的部分前缀和。

  时间复杂度...我也不知道,大概在$O(n^{\frac{3}{4}})$左右吧...

  

#include<bits/stdc++.h>
#define mod 1000000007
#define ll long long
#define N 20000010
using namespace std;
int pr[N],mu[N],t[N],d[N];
ll n,ans;
bitset<N>vis;
void make(int m)
{
mu[] = d[] = ;
for(int i = ;i<=m;i++)
{
if(!vis[i])pr[++pr[]] = i,mu[i] = -,d[i] = ;
for(int j = ;i*pr[j]<=m;j++)
{
vis[i*pr[j]] = ;
d[i*pr[j]] = d[i]<<;
if(i%pr[j]==){d[i*pr[j]]-=d[i/pr[j]];break;}
mu[i*pr[j]] = -mu[i];
}
}for(int i = ;i<=m;i++)t[i] = t[i-]+mu[i]*mu[i],d[i] = (d[i]+d[i-])%mod;
}
ll S(ll m)//mu^2[i]前缀和
{
if(m<=)return t[m];
ll ret = ,tt = (ll)sqrt(m)+;
for(ll i = ;i<=tt;i++)ret+=mu[i]*(m/i/i);
return ret;
}
ll SS(ll m)//d(i)前缀和
{
if(m<=)return d[m];
ll ret = ,nxt;
for(ll i = ;i<=m;i = nxt+)
{
nxt = m/(m/i);
ret = (ret+(m/i)*(nxt-i+)%mod)%mod;
}return ret;
}
int main()
{
scanf("%lld",&n);
make();
ans = (n%mod)*(n%mod)%mod;
ll nxt;
for(ll i = ;i<=n;i = nxt+)
{
nxt = n/(n/i);
ans = (ans-(S(nxt)-S(i-))%mod*SS(n/i)%mod)%mod;
}printf("%lld\n",(ans+mod)%mod);
return ;
}

最新文章

  1. 阿里云系列——6.给你的域名使用CDN加速(详细步骤+简单配置)
  2. VBA中如何动态定义数组
  3. Remoting和Webservice的区别
  4. [AaronYang]C#人爱学不学[3]
  5. 高可用集群heartbeat全攻略
  6. ajax读取json数据
  7. html中的div、td 、p 等容器内强制换行和不换行的实现
  8. POJ 2435Navigating the City(bfs)
  9. (转)$.extend()方法和(function($){...})(jQuery)详解
  10. CSS( Cascading Style Sheets )简书
  11. python的bit_length方法
  12. suse 12 sp1 系统添加zabbix agent监控
  13. C#LinQ语法
  14. MOngoDB为现有数据添加或删除某一字段
  15. Android-Java-同步方法-synchronized
  16. PS小技巧之完美抠图
  17. echart知识点、常用图形
  18. Linux下分析磁盘镜像
  19. C++基本规则
  20. 配置consul为windows服务

热门文章

  1. sleuth和zipkin微服务里的链路跟踪
  2. Class文件结构-常量池
  3. 使用 docker 部署常用的开发环境
  4. CentOS7 如何升级Git
  5. tomcat启停脚本
  6. C# 执行 cmd 命令, 不显示任何窗口
  7. 关于eclipse中启动tomcat提示启动超时问题
  8. 阿里云 centOS系统 配置 node + ngnix
  9. Java之属性集(Properties类)
  10. Java之Collection接口(单列集合根接口)