题目链接

题意

给出n个数,问在这n个数里面,有多少组bi(1<=bi<=ai)可以使得任意两个bi不互质。

思路

想法就是枚举2~min(ai),然后去对于每个ai都去除以这些质数,然后再相乘就代表对于这个数有多少种。但是这样的想法会超时的还会算重复。

那么考虑分段计数,处理一个前缀和,代表sum[1~i]这段区间出现了多少个ai,然后对于每个因子都去枚举它的倍数,因为这段区间里面的数对于这个因子的贡献是相同的,于是可以有pow(倍数, sum[r] - sum[l-1])的贡献,这样的复杂度为nlognlogn。但是还有一个重要的问题,就是会算重复,例如当因子为2和4和6的情况。

这个时候就要用到莫比乌斯反演

我觉得莫比乌斯反演就是用在有约数关系时候的容斥原理。处理出来的表的时间复杂度是O(n)的。

比较常用的意义:

$ F(n) $ 表示约数为n的组数有多少。

$ f(n) $ 表示最大公约数为n的组数有多少。

\[F(n)=\sum_{d|n}f(d)
\]

d|n表示d为n的因子。

\[f(n)=\sum_{n|d}\mu(i)F(\frac{d}{i})
\]

一般我们求 $ f(1) $ 就是求gcd为1即互质的情况下的组数,这道题求的是不互质,即为 $ f(2) + f(3) + f(4) … + f(min(a)) $ 这个情况下要把 $ \mu(d) $ 乘个-1。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
typedef long long LL;
int vis[N], mu[N], prime[N], sum[N*2]; void mobius(int n) {
mu[1] = 1;
for(int i = 1; i <= n; i++) {
for(int j = 2 * i; j <= n; j += i) {
mu[j] -= mu[i];
}
}
memset(vis, 0, sizeof(vis));
mu[1] = 1; int cnt = 0;
for(int i = 2; i <= n; i++) {
if(!vis[i]) {
prime[cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < cnt && i * prime[j] <= n; j++) {
vis[i * prime[j]] = 1;
if(i % prime[j]) mu[i*prime[j]] = -mu[i];
else { mu[i*prime[j]] = 0; break; }
}
}
} LL f_pow(LL a, int b) {
LL ans = 1;
while(b) {
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
} return ans % MOD;
} int main() {
int t; scanf("%d", &t);
mobius(100000);
for(int cas = 1; cas <= t; cas++) {
int n; scanf("%d", &n);
memset(sum, 0, sizeof(sum));
int mi = N, ma = 0;
for(int i = 1; i <= n; i++) {
int a; scanf("%d", &a);
sum[a]++;
if(a < mi) mi = a;
if(a > ma) ma = a;
}
for(int i = 1; i < 2 * N; i++) sum[i] += sum[i-1];
LL ans = 0;
for(int i = 2; i <= mi; i++) {
LL tmp = 1, k = 1; for(int j = i; j <= ma; j += i, k++)
tmp = tmp * f_pow(k, sum[j+i-1] - sum[j-1]) % MOD; // 在j到j+i-1这段区间里面整除i的有k个数 ans = (ans - tmp * mu[i] + MOD) % MOD;
}
printf("Case #%d: %lld\n", cas, (ans + MOD) % MOD);
}
return 0;
}

最新文章

  1. cocos2dx-lua_修改源码流程(cocos2dx-3.10、win7、Cocos Code IDE1.2)
  2. 友盟SDK实现分享
  3. 设置TextBox控件的TextMode属性
  4. 如何才能恢复Excel文档的打开密码
  5. codeforces VK cup 2016-round 1 D.Bear and Contribution
  6. iOS开发Swift篇—(三)字符串和数据类型
  7. 如何发布使用LGPL版Qt的商业软件
  8. angularJS学习手册(1)
  9. actionBar兼容2.1及以上版本的做法 .
  10. intel线程库tbb的使用
  11. 《C++ Primer》之面向对象编程(二)
  12. 访问taotao-portal 中controller中返回taotaoresult 测试httppost方法 出现406错误
  13. SimpleXML系列函数操作XML
  14. ElasticSearch(十二)删除数据插件delete-by-query
  15. 006.Ceph对象存储基础使用
  16. 高性能迷你React框架anujs1.0.5发布
  17. oracle 远程导入导出(本地win)
  18. HTML中JavaScript调用方法
  19. Mybatis中#和$区别(带脑图)
  20. [spring] 对实体 &quot;characterEncoding&quot; 的引用必须以 &#39;;&#39; 分隔符结尾

热门文章

  1. U3D游戏开发商思考
  2. Servlet的基础知识
  3. IIS文件目录
  4. XF内容视图和框架
  5. JAVASCRIPT高程笔记-------第六章 面向对象的程序设计
  6. WM_CopyData 用法
  7. XAML的命名空间
  8. 百度蜘蛛ip段代表的不同含义
  9. 支持chrome30下载文件
  10. QList, QLinkedList, QVector, QStack, QQueue的区别,以前也没见过QCache,而且可以自定义cost