CQOI2015 选数
题目
从\([L, H]\)(\(H-L\leq 10^5\))选出\(n\)个整数,使得这些数的最大公约数为\(k\)的方案数。
算法
首先有一个很简单的转化,原问题可以简化为:
从\([\lceil {\frac L k} \rceil, \lfloor {\frac H k} \rfloor]\)中选出\(n\)个整数,使得这些数的最大公约数为\(1\)的方案数。
下面,\(L\)的意义不再是原题的意义了,而是\(\lceil {\frac L k} \rceil\),\(H\)同理。
算法1
设\(dp(i)\)为从选出的这些数最大公约数的为\(i\)的方案数。那么我们可以得到:
\]
然后我们就这样DP就有\(80\)分了,时间复杂度\(O(H)\)(这里的\(H\)不是指的是题目中的\(H\),而是重新定义的\(H\))。
算法2
对上面的DP进行莫比乌斯反演。
设\(F(i)\)为选出的数的最大公约数能够被\(i\)整除的方案数,那么:
\]
反演得:
\]
我们求的是\(dp(1)\),所以\(d=1\)。
\]
这个算起来也是\(O(H)\)的,但是我们还可以继续化简下去。注意到题目中的条件\(H-L\leq 10^5\)。
当\(i \geq H-(L-1)\),即\(i > H - L\)的时候,我们可以发现一个很神奇的东西,那就是\(\lfloor {\frac H i} \rfloor - \lfloor {\frac {L - 1} i}\rfloor\)要么等于\(0\),要么等于\(1\),所以我们可以把指数去掉!
\]
加号左边的式子我们可以暴力算出,现在问题是右边那个怎么算。我们可以计算它的补集:
\]
减号右边的式子我们又可以暴力算出,而左边的,注意到它就是原问题,不过此时\(n=1\)。
原问题:\(\sum_{i=1}^H\mu(i)(\lfloor {\frac H i} \rfloor - \lfloor {\frac {L - 1} i}\rfloor)^n\)
现在我们求的:\(\sum_{i=1}^H\mu(i)(\lfloor {\frac H i} \rfloor-\lfloor {\frac {L - 1} i}\rfloor)\)
这样,我们的问题是:从\([L, H]\)中选出\(1\)个整数,使得这些数的最大公约数为\(1\)的方案数。
这个问题的答案就是\(\sum_{i=1}^H\mu(i)(\lfloor {\frac H i} \rfloor-\lfloor {\frac {L - 1} i}\rfloor)\),若\(L=1\),那么式子的值就是\(1\),否则就是\(0\)。
至此,我们就巧妙地解决这道题,时间复杂度\(O(H-L)\)。
代码
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long i64;
const int MAXN = (int) 1e5 + 3;
const int MOD = (int) 1e9 + 7;
int H, L, n;
int myPower(int a, int b) {
int ans = 1;
while (b) {
if (b & 1)
ans = (i64) ans * a % MOD;
a = (i64) a * a % MOD;
b >>= 1;
}
return ans;
}
int main() {
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
int k;
scanf("%d%d%d%d", &n, &k, &L, &H);
L = (L + k - 1) / k;
H = H / k;
int HL = H - L;
static bool notPrime[MAXN];
static int prime[MAXN], cntPrime;
static int mu[MAXN];
static int fac[MAXN];
mu[1] = 1;
for (int i = 2; i <= HL; i ++) {
if (! notPrime[i]) {
prime[cntPrime ++] = i;
mu[i] = -1;
fac[i] = i;
}
for (int k = 0; k < cntPrime; k ++) {
int j = prime[k];
if (j > fac[i]) break;
if ((i64) j * i > HL) break;
notPrime[j * i] = true;
mu[j * i] = fac[i] == j ? 0 : mu[i] * -1;
fac[j * i] = j;
}
}
i64 ans = 0;
for (int i = 1; i <= HL; i ++) {
ans += (i64) mu[i] * myPower(H / i - (L - 1) / i, n);
ans %= MOD;
}
if (L == 1) ans ++;
for (int i = 1; i <= HL; i ++) {
ans -= mu[i] * (H / i - (L - 1) / i);
ans %= MOD;
}
cout << (ans + MOD) % MOD << endl;
return 0;
}
算法3
设\(f(i)\)为选出的数的最大公约数为\(i\)且选出的这些数不能全部是同一个数的方案数。
然后我们又可以得到:$$f(i)=(\lfloor {\frac H i} \rfloor - \lfloor {\frac {L - 1} i}\rfloor)^n-(\lfloor {\frac H i} \rfloor - \lfloor {\frac {L - 1} i}\rfloor)-\sum_{i|j,i < j}f(j)$$
可以发现,这里的\(i\)最大只有\(H-L\),因为对于任意正整数\(x,y(x\neq y)\),都有\(gcd(x, y)\leq |x-y|\)。
然后我们要加上允许全部数选同一个数的方案。
算法4
CQOI2015 选数的更多相关文章
- BZOJ 3930: [CQOI2015]选数 递推
3930: [CQOI2015]选数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pro ...
- bzoj3930[CQOI2015]选数 容斥原理
3930: [CQOI2015]选数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1383 Solved: 669[Submit][Status] ...
- 洛谷 [CQOI2015]选数 解题报告
[CQOI2015]选数 题目描述 我们知道,从区间\([L,H]\)(\(L\)和\(H\)为整数)中选取\(N\)个整数,总共有\((H-L+1)^N\)种方案. 小\(z\)很好奇这样选出的数的 ...
- 【BZOJ3930】[CQOI2015]选数 莫比乌斯反演
[BZOJ3930][CQOI2015]选数 Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律 ...
- [CQOI2015]选数(莫比乌斯反演,杜教筛)
[CQOI2015]选数(luogu) Description 题目描述 我们知道,从区间 [L,H](L 和 H 为整数)中选取 N 个整数,总共有 (H-L+1)^N 种方案. 小 z 很好奇这样 ...
- BZOJ3930: [CQOI2015]选数
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3930 容斥原理. 令l=(L-1)/k,r=R/k,这样找k的倍数就相当于找1的倍数. 设F[ ...
- 【刷题】BZOJ 3930 [CQOI2015]选数
Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公 ...
- 【BZOJ】3930: [CQOI2015]选数
题意 从区间\([L, R]\)选\(N\)个数(可以重复),问这\(N\)个数的最大公约数是\(K\)的方案数.(\(1 \le N, K \le 10^9, 1 \le L \le R \le 1 ...
- bzoj 3930: [CQOI2015]选数
Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公 ...
随机推荐
- BZOJ 1782: [Usaco2010 Feb]slowdown 慢慢游( BIT + dfs )
orz...hzwer 对着大神的 code 看 , 稍微理解了. 考虑一只牛到达 , 那它所在子树全部 +1 , 可以用BIT维护 --------------------------------- ...
- JS 控制 form是否提交表单
问题背景:用php删除数据,希望在点击“删除”(button)的时候JS弹出confirm来确认是否删除. 此段代码为php中的form: <form action="?form=de ...
- json对象的操作,json工具
项目中经常用到json,现在把写了几个js函数,用来获取json对象或者json字符串的长度,以及获取其的key值,value值,并且返回. 这样以后可以直接拿来用,可以省去不少麻烦,也方便以后查看. ...
- eclipse没有New Java Class的解决办法
配置之前的截图: 配置步骤:
- gdb调试相关
GDB调试及其调试脚本的使用返回脚本百事通一.GDB调试 1.1. GDB 概述 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等 ...
- Ubuntu基本设置
(1) 为了启用 root 帐号 (也就是 设置一个口令) 使用: sudo passwd root 1.设置IP, 终端输入 sudo gedit /etc/network/interfaces ...
- Android 网络交互之MD5为什么要加盐
MD5为什么要加盐 之前面试的时候,遇到一个面试的哥哥.不停的跟我确认我对网络传输过程中的password进行MD5加密的时候,是否加key了. 当时我很纳闷,因为MD5本身已经是不可逆的了,需要破解 ...
- kinect for windows - 初认识
kinect是微软开发的一种计算机输入设备,原来只是用于xbox,kinect负责捕捉用户的动作,让xbox游戏做出相应的反应.很快大家对此非常有兴趣,因此有些geek和组织为kinect开发了驱动和 ...
- Windows XP硬盘安装Ubuntu 12.04双系统图文详解
Windows XP硬盘安装Ubuntu 12.04双系统图文详解 Ubuntu 12.04 LTS版本于2012年4月26日发布,趁着五一放假,赶紧在自己的Windows XP的电脑上安装下Ubun ...
- Battle ships(二分图,建图,好题)
Battle ships Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tot ...