传送门


数字最小公倍数为\(L\)的充分条件是所有数都是\(L\)的约数,而\(10^8\)内最多约数的数的约数也只有\(768\)个。所以我们先暴力找到所有满足是\(L\)的约数、\(G\)的倍数的数。

接下来注意到题目的\(\gcd\)和\(lcm\)的限制等价于对于每一个质数限制所有数在该质数指数上的\(\min\)和\(\max\)。在\(10^8\)内质数数量最多的数只有\(8\)个质数,所以我们对于第一步中求出的数用一个二进制数记录下它每一个质数的指数是否等于限制的\(\min\)和\(\max\)。那么问题就变成了选择子集满足按位或为全集的方案数。

对于这个问题考虑容斥,即强制某些位置在或的过程当中不被取到,那么答案就是\(\sum\limits_{S \subseteq U} (-1)^{|S|} 2^{\sum\limits_{j \subseteq U-S}1}\)。

后面的\(\sum\limits_{j \subseteq U-S}1\)可以通过高维前缀和求得。

最后我们需要求出所有数字的答案,那么我们只需要先算出所有数都可选择的答案,然后把当前数从高维前缀和中删掉计算其他数可以选择的答案相减即可。

复杂度\(O(2^{2\omega(n)} d(n)+Q)\),其中\(\omega(n),d(n)\)分别是质数个数、约数个数。

#include<bits/stdc++.h>
using namespace std; const int MOD = 1e9 + 7; map < int , int > ans;
int prm , Pow2[800] , cnt[1 << 16] , N , G , L , Q; vector < int > num , val; int poww(long long a , int b){
int times = 1;
while(b){
if(b & 1) times = times * a % MOD;
a = a * a % MOD; b >>= 1;
}
return times;
} void calc(int id , int x){
int p = G , q = L , cnt1 = 0 , cnt2 = 0;
while(p % x == 0){++cnt1; p /= x;}
while(q % x == 0){++cnt2; q /= x;}
for(int j = 0 ; j < num.size() ; ++j){
int cur = num[j] , cnt = 0;
while(cur % x == 0){++cnt; cur /= x;}
if(cnt == cnt1) val[j] |= 1 << id;
if(cnt == cnt2) val[j] |= 1 << (id + prm);
}
} int main(){
cin >> N >> G >> L >> Q;
if(L % G){for(int i = 1 ; i <= Q ; ++i) cout << "0\n"; return 0;} for(int i = 1 ; i <= N && i * i <= L ; ++i)
if(L % i == 0){
if(i % G == 0) num.push_back(i);
if(L / i <= N && L / i != i && (L / i) % G == 0) num.push_back(L / i);
} int tp = L; val.resize(num.size());
for(int i = 2 ; i * i <= tp ; ++i) if(tp % i == 0){++prm; while(tp % i == 0) tp /= i;}
if(tp - 1) ++prm; tp = L; int tc = 0;
for(int i = 2 ; i * i <= tp ; ++i)
if(tp % i == 0){calc(tc++ , i); while(tp % i == 0) tp /= i;}
if(tp - 1) calc(tc++ , tp); for(int i = 0 ; i < val.size() ; ++i) ++cnt[val[i]];
for(int i = 0 ; i < 2 * prm ; ++i)
for(int j = 0 ; j < 1 << (2 * prm) ; ++j)
if(j >> i & 1) cnt[j] += cnt[j ^ (1 << i)];
Pow2[0] = 1; for(int i = 1 ; i <= num.size() ; ++i) Pow2[i] = (Pow2[i - 1] << 1) % MOD;
int all = 0;
for(int j = 0 ; j < 1 << (2 * prm) ; ++j)
all = (all + (__builtin_popcount(j) & 1 ? MOD - 1ll : 1ll) * Pow2[cnt[j]]) % MOD; for(int i = 0 ; i < num.size() ; ++i){
int sum = 0;
for(int j = 0 ; j < 1 << (2 * prm) ; ++j) if((val[i] & j) == val[i]) --cnt[j];
for(int j = 0 ; j < 1 << (2 * prm) ; ++j)
sum = (sum + (__builtin_popcount(j) & 1 ? MOD - 1ll : 1ll) * Pow2[cnt[j]]) % MOD;
ans[num[i]] = (all + MOD - sum) % MOD;
for(int j = 0 ; j < 1 << (2 * prm) ; ++j) if((val[i] & j) == val[i]) ++cnt[j];
} while(Q--){int x; cin >> x; cout << ans[x] << endl;}
return 0;
}

LOJ2257 SNOI2017 遗失的答案 容斥、高维前缀和的更多相关文章

  1. BZOJ4036:按位或 (min_max容斥&高维前缀和)

    Description 刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行或(c++,c的|,pascal 的or)操作.选择数字i的概率是p[i].保证0&l ...

  2. [luogu 3175] [HAOI2015]按位或(min-max容斥+高维前缀和)

    [luogu 3175] [HAOI2015]按位或 题面 刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行按位或运算.问期望多少秒后,你手上的数字变成2^n ...

  3. Codeforces.449D.Jzzhu and Numbers(容斥 高维前缀和)

    题目链接 \(Description\) 给定\(n\)个正整数\(a_i\).求有多少个子序列\(a_{i_1},a_{i_2},...,a_{i_k}\),满足\(a_{i_1},a_{i_2}, ...

  4. luoguP3175 [HAOI2015]按位或 min-max容斥 + 高维前缀和

    考虑min-max容斥 \(E[max(S)] = \sum \limits_{T \subset S} min(T)\) \(min(T)\)是可以被表示出来 即所有与\(T\)有交集的数的概率的和 ...

  5. 【BZOJ5019】[SNOI2017]遗失的答案(FWT,动态规划)

    [BZOJ5019][SNOI2017]遗失的答案(FWT,动态规划) 题面 BZOJ 题解 发现\(10^8\)最多分解为不超过\(8\)个本质不同质数的乘积. 而\(gcd\)和\(lcm\)分别 ...

  6. [Hdu-6053] TrickGCD[容斥,前缀和]

    Online Judge:Hdu6053 Label:容斥,前缀和 题面: 题目描述 给你一个长度为\(N\)的序列A,现在让你构造一个长度同样为\(N\)的序列B,并满足如下条件,问有多少种方案数? ...

  7. luogu P5366 [SNOI2017]遗失的答案

    luogu 首先gcd为\(G\),lcm为\(L\),有可能出现的数(指同时是\(G\)的因数以及是\(L\)的倍数)可以发现只有几百个.如果选出的数要能取到gcd,那么对于每种质因子,都要有一个数 ...

  8. BZOJ5019 SNOI2017遗失的答案(容斥原理)

    显然存在方案的数一定是L的因数,考虑对其因子预处理答案,O(1)回答. 考虑每个质因子,设其在g中有x个,l中有y个,则要求所有选中的数该质因子个数都在[x,y]中,且存在数的质因子个数为x.y.对于 ...

  9. BZOJ5019[Snoi2017]遗失的答案——FWT+状压DP

    题目描述 小皮球在计算出答案之后,买了一堆皮肤,他心里很开心,但是一不小心,就忘记自己买了哪些皮肤了.==|||万 幸的是,他还记得他把所有皮肤按照1-N来编号,他买来的那些皮肤的编号(他至少买了一款 ...

随机推荐

  1. 25. Apache Shiro Java反序列化漏洞

    前言: 最近在审核漏洞的时候,发现尽管Apache shiro这个反序列化漏洞爆出来好久了,但是由于漏洞特征不明显,并且shiro这个组件之前很少听说,导致大厂很多服务还存在shiro反序列化的漏洞, ...

  2. web-api POST body object always null

      If the any of values of the request's JSON object are not the same type as expected by the service ...

  3. bat 获取管理员权限,判断系统位数,获取当前文件所在目录,regsvr32注册DLL、OCX

    1.获取管理员权限 @echo off if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%Syste ...

  4. docker上启动mysql镜像,mysq中记录乱码解决方法

    在docker上启动一个mysql, 1. docker pull mysql 2. docker run --name mysql_dev -p 3306:3306 -e MYSQL_ROOT_PA ...

  5. javascript之DOM(二Document对象)

    javascript通过Document类型来表示文档.在浏览器中document是HTMLDocument对象(继承自Document)的一个实例,表示整个html页面.而且在浏览器中documen ...

  6. 【Appium】Android 按键码

    keycode也是appium很强大的功能,鉴于官网不翻墙无法打开,特此备忘. 电话键     KEYCODE_CALL 拨号键 5 KEYCODE_ENDCALL 挂机键 6 KEYCODE_HOM ...

  7. matplotlib 自带的几种美化样式

    1.用 matplotlib.pyplot.style.avaliable 可查看 matplotlib 自带的美化样式如下: ['bmh', 'classic', 'dark_background' ...

  8. 1. Ubuntu下使用pip方式安装tensorflow

    参考文档: https://tensorflow.google.cn/install/pip 首先明确,我们采用python3环境. 1. 先确认本机已安装好python3的环境 python3 -- ...

  9. Java精通并发-Condition编程模式详解与分析

    继续上一次https://www.cnblogs.com/webor2006/p/11890688.html的Condition接口说明进行阅读: 上面这个程序会在之后手动来实现一下,说实话这种写法在 ...

  10. 从架构开始谈dubbo(二)-----zookeeper安装和dubbo文档查阅

    一.Zookeeper下载与安装 1.官网地址下载 https://zookeeper.apache.org/ 2.找到图中英文位置(英文不好,安图操作就好了,计算机很多东西如果你没法很好的记忆,就画 ...