传送门


数字最小公倍数为\(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. win中Oracle简易客户端和plsql的配置

    连接数据库有2种方式:在本机安装Oracle数据库或者是安装一个oracle简易客户端 当然,简易客户端跟oracle数据库比较少了一些功能 连接方式: 1)简易连接 sqlplus scott/ti ...

  2. Python学习日记(四十) Mysql数据库篇 八

    Mysql存储过程 存储过程是保存在Mysql上的一个别名(就是一堆SQL语句),使用别名就可以查到结果不用再去写SQL语句.存储过程用于替代程序员写SQL语句. 创建存储过程 delimiter / ...

  3. Linux服务之DNS介绍

    DNS-------Domain Name System域名系统 介绍:DNS就是把域名和IP地址联系在一起的服务,有了DNS服务器,你就不用输入IP地址来访问一个网站,可以通过输入网址访问.     ...

  4. centos自动同步服务器时间

    原文:https://my.oschina.net/yysue/blog/1628733 1.安装ntpdate yum install ntpdate -y 2.测试是否正常 ntpdate cn. ...

  5. Nginx+lamp构建动静分离项目

    一.nginx代理的概述 概述:nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:nginx可以作为一个内部网络代理上网的代理 ...

  6. 第05节-BLE协议物理层(PHY)

    对于软件的人来说,物理层关注的内容会少一点.在前面的博客中,我们以快递员类比物理层,对于快递员来说,道路千万条,这条不通换另外一条.对于物理层来说也是一样的,它有很多频率,这个频率有冲突了,将会切到另 ...

  7. PHP将图片转base64格式函数

    base64的好处是什么?今天在跟小伙伴讨论这个问题,要是全站用Php把图片转为base64行不行? 1. 提升性能: 网页上的每一个图片,都是需要消耗一个 http 请求下载而来的, 图片的下载始终 ...

  8. NOIP 2008 立体图

    洛谷 P1058 立体图 洛谷传送门 JDOJ 1541: [NOIP2008]立体图 T4 JDOJ传送门 题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣的内容.最近,他准备 ...

  9. 2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)

    2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) 全靠 wxh的博客 补完这套.wx ...

  10. 【oracle】decode函数

    DECODE(参数,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值) 值1:当参数=值1    翻译值1:想要得到的值 值2:当参数=值2 翻译值2:想要得到的值