题目描述

小皮球在计算出答案之后,买了一堆皮肤,他心里很开心,但是一不小心,就忘记自己买了哪些皮肤了。==|||万
幸的是,他还记得他把所有皮肤按照1~N来编号,他买来的那些皮肤的编号(他至少买了一款皮肤),最大公约数
是G,最小公倍数是L。现在,有Q组询问,每组询问输入一个数字X,请你告诉小皮球,有多少种合法的购买方案中
,购买了皮肤X?因为答案太大了,所以你只需要输出答案mod1000000007即可。

输入

第一行,三个数字N,G,L,如题意所示。
第二行,一个数字Q,表示询问个数。
第三行,Q个数字,表示每个询问所问的X。
N,G,L≤10^8,Q≤10^5,1≤X≤10^8

输出

对于每一组询问,在一行中单独输出一个整数,表示这个询问的答案。

样例输入

5 1 30
5
1 2 3 4 5

样例输出

1
2
2
0
2
 
将每个数质因数分解,那么$GCD$和$LCM$就分别是每个质因子的最小幂次的乘积和最大幂次的乘积。
一个不大于$10^8$的数最多有$8$个不同的质因子,可以考虑用状压来记录每个质因子的幂次的最大值和最小值是否达到了$GCD$和$LCM$的标准。
设$f[i][S1][S2]$表示前$i$个数的质因子的最小幂次是否达到的状态为$S1$,最大幂次是否达到的状态为$S2$时的方案数(为了方便,可以将$S1,S2$合并为一维)。
因为选取的数必须是$GCD$的倍数和$LCM$的约数,所以最多不会超过$600$个选取的数。
每次询问要指定必须选取某个数,我们记录前缀$DP$数组和后缀$DP$数组。
对于强制选取第$i$个数的情况,显然要将$i-1$的前缀$DP$数组和$i+1$的后缀$DP$数组合并,用或运算$FWT$合并即可。
那么对于合并后的$DP$数组,只要二进制状态是全集去掉第$i$个数的状态后的状态的父集就都合法,用与运算$FWT$正变换一下合并之后的$DP$数组即可。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int mod=1000000007;
const int inv=500000004;
bool vis[10010];
int prime[10010];
int cnt;
int G,L,Q;
int n,x;
int num;
int sum;
int mask;
int mx[10];
int pr[10];
int f[1<<16];
int g[1<<16];
int tmp[1<<16];
int p[1<<16];
int res[1<<16];
int pre[600][1<<16];
int suf[600][1<<16];
void find()
{
for(int i=2;i<=10000;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&prime[j]*i<=10000;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
break;
}
}
}
}
void FWT_OR(int *a,int len,int opt)
{
for(int k=2;k<=len;k<<=1)
{
int t=k>>1;
for(int i=0;i<len;i+=k)
{
for(int j=i;j<i+t;j++)
{
if(opt==1)
{
a[j+t]=(a[j+t]+a[j])%mod;
}
else
{
a[j+t]=(a[j+t]-a[j]+mod)%mod;
}
}
}
}
}
void FWT_AND(int *a,int len,int opt)
{
for(int k=2;k<=len;k<<=1)
{
int t=k>>1;
for(int i=0;i<len;i+=k)
{
for(int j=i;j<i+t;j++)
{
if(opt==1)
{
a[j]=(a[j]+a[j+t])%mod;
}
else
{
a[j]=(a[j]-a[j+t]+mod)%mod;
}
}
}
}
}
void take(int x)
{
for(int i=1;i<=cnt&&prime[i]*prime[i]<=x;i++)
{
if(x%prime[i]==0)
{
pr[++num]=prime[i];
while(x%prime[i]==0)
{
x/=prime[i];
mx[num]++;
}
}
}
if(x>1)
{
pr[++num]=x,mx[num]=1;
}
}
int quick(int x,int y)
{
int res=1;
while(y)
{
if(y&1)
{
res=1ll*res*x%mod;
}
y>>=1;
x=1ll*x*x%mod;
}
return res;
}
void dfs(int dep,int x,int S1,int S2)
{
if(dep>num)
{
res[S1|(S2<<num)]++;
return ;
}
for(int i=0;i<=mx[dep];i++)
{
dfs(dep+1,x,S1|((i==0)<<(dep-1)),S2|((i==mx[dep])<<(dep-1)));
if(1ll*x*pr[dep]>n)
{
return ;
}
x*=pr[dep];
}
}
void add(int &x,int y)
{
x+=y;
if(x>mod)
{
x-=mod;
}
}
int get(int x)
{
int S=0;
for(int i=1;i<=num;i++)
{
int ans=0;
while(x%pr[i]==0)
{
x/=pr[i],ans++;
}
if(!ans)
{
S|=1<<(i-1);
}
if(ans==mx[i])
{
S|=1<<(i-1+num);
}
}
return S;
}
int main()
{
scanf("%d%d%d%d",&n,&G,&L,&Q);
find();
if(L%G)
{
while(Q--)
{
puts("0");
}
return 0;
}
L/=G,n/=G;
take(L);
dfs(1,1,0,0);
mask=1<<(num+num);
for(int i=0;i<mask;i++)
{
if(res[i])
{
g[++sum]=i;
p[sum]=quick(2,res[i])-1;
}
}
f[0]=1,pre[0][0]=1;
for(int i=1;i<=sum;i++)
{
for(int j=0;j<mask;j++)
{
add(tmp[j|g[i]],1ll*f[j]*p[i]%mod);
}
for(int j=0;j<mask;j++)
{
add(f[j],tmp[j]),tmp[j]=0;
}
for(int j=0;j<mask;j++)
{
pre[i][j]=f[j];
}
}
memset(f,0,sizeof(f));
f[0]=1,suf[sum+1][0]=1;
for(int i=sum;i>=1;i--)
{
for(int j=0;j<mask;j++)
{
add(tmp[j|g[i]],1ll*f[j]*p[i]%mod);
}
for(int j=0;j<mask;j++)
{
add(f[j],tmp[j]),tmp[j]=0;
}
for(int j=0;j<mask;j++)
{
suf[i][j]=f[j];
}
}
for(int i=0;i<=sum;i++)
{
FWT_OR(pre[i],mask,1);
FWT_OR(suf[i+1],mask,1);
}
for(int i=0;i<sum;i++)
{
for(int j=0;j<mask;j++)
{
pre[i][j]=1ll*pre[i][j]*suf[i+2][j]%mod;
}
}
for(int i=0;i<sum;i++)
{
FWT_OR(pre[i],mask,-1);
FWT_AND(pre[i],mask,1);
}
while(Q--)
{
scanf("%d",&x);
if(x%G){puts("0");continue;}
x/=G;
if(L%x){puts("0");continue;}
if(x>n){puts("0");continue;}
int S=get(x);
int ans=0;
int y=lower_bound(g+1,g+1+sum,S)-g-1;
ans=pre[y][(mask-1)^S];
ans=1ll*ans*inv%mod*(p[y+1]+1)%mod;
printf("%d\n",ans);
}
}

BZOJ5019[Snoi2017]遗失的答案——FWT+状压DP的更多相关文章

  1. bzoj5019: [Snoi2017]遗失的答案

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

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

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

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

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

  4. Luogu4221 WC2018州区划分(状压dp+FWT)

    合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...

  5. [WC2018]州区划分(状压DP+FWT/FMT)

    很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...

  6. bzoj 5019 [Snoi2017]遗失的答案

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=5019 题解 如果L不是G的倍数 答案为0 下面考虑G|L的情况 将G,L质因数分解 设$L= ...

  7. 洛谷$P5366\ [SNOI2017]$遗失的答案 数论+$dp$

    正解:数论$dp$ 解题报告: 传送门$QwQ$ 考虑先质因数分解.所以$G$就相当于所有系数取$min$,$L$就相当于所有系数取$max$ 这时候考虑,因为数据范围是$1e8$,$1e8$内最多有 ...

  8. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  9. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

随机推荐

  1. python3-随机生成10位包含数字和字母的密码

    方法一: 知识点:random.sample(sequence, k) 从指定序列中随机获取指定长度的片断 import random,string num=string.ascii_letters+ ...

  2. 第一册:lesson 115.

    原文:Knock,Knock! question:What does Jim have to drink? Isn't there anyone at home? I'll knock again , ...

  3. Java多线程小总结

    多线程 线程与进程 线程:具有完成特定任务的一条执行路径,是CPU执行的最小单位 进程:正在执行的程序 重点:CPU在某个时间刻度上只能够执行一条原子性语句 字节最小是bit位 原子性语句:不能够再次 ...

  4. 中介者模式 调停者 Mediator 行为型 设计模式(二十一)

      中介者模式(Mediator)   调度.调停   意图 用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散 而且可以独立地改变它们之间的交互. ...

  5. html 微信video放大后无法返回问题

    android  video播放视频放大后无法返回,先debug下debugx5.qq.com 发现用的不是X5内核 直接激活  debugmm.qq.com/?forcex5=true  问题解决 ...

  6. vue 使用定时器setInterval

    来自:https://www.jianshu.com/p/180957762852 侵删 beforeMount() { //车辆进出设置定时器,每3秒刷新一次 var self = this; cl ...

  7. 山西大同大学教务处教师端——可在PC端,手机端操作

    解决问题:大同大学教务处官网教师端口一进去就卡住了,点上面一行的菜单无响应 下载方法(学生端 / 教师端  / 验证脚本): 链接:https://pan.baidu.com/s/1MWrJXoPzE ...

  8. Android studio怎么使用自定义的framework而避免冲突报错和点不进去报红。

    文件:xx\project_abc\video\build.gradle保证可以运行到自定义的framework而不报错,可能因为project和module名字相同所以导致下面的路径是绝对路径,其他 ...

  9. Python 经典面试题汇总之网络篇

    网络篇 1.简述 OSI 七层协议 物理层:定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质. 数据链路层:定义如何传输格式化数据,以及如何访问物理介质. 网络层:定义逻辑网络地址. ...

  10. SQL大全基本语法

    一.基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql server --- ...