题目

首先\(G,L\)肯定会满足\(G|L\),否则直接全部输出\(0\)

之后我们考虑一下能用到的质因数最多只有\(8\)个

同时我们能选择的数\(x\)肯定是\(L\)的约数,还得是\(G\)的倍数,还不能超过\(N\),感性理解一下这样的\(x\)显然不多,我们直接\(dfs\)出来

对于每一个数我们把它压成一个\(2\times 8\)的二进制数,第\(2i-1,2i\)位分别表示第\(i\)个质因子是否到上界/下界,我们直接一个\(dp[i][j]\)表示前\(i\)个数选择状态为\(j\)的方案数,同时我们还能处理出一个后缀的\(dp\)值来

对于一个必须选择的\(x\),我们用前缀和后缀做一下或\(FWT\),求所有和这个数的状态或起来为全集的位置的和就好了

复杂度看起来不是很科学,但是常数比较小,就跑过去了

代码

#include <bits/stdc++.h>
#define re register
const int mod = 1e9 + 7;
inline int read() {
char c = getchar();
int x = 0;
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - 48, c = getchar();
return x;
}
std::map<int, int> ma;
int N, G, L, Q, M, n, len;
int f[50005], p[20005];
int cnt[2], b[10], a[10][2], l[10], r[10], beg[10];
int c[850], st[850], ans[850], vis[850];
int dp[850][65537], tp[850][65537], d[65537];
void dfs(int x, int now, int S) {
if (x == cnt[0] + 1) {
c[++n] = now, st[n] = S;
return;
}
int t = beg[x];
for (re int i = l[x]; i <= r[x]; ++i)
if (now <= N / t) {
int s = S;
if (i == l[x])
s |= (1 << (2 * x - 2));
if (i == r[x])
s |= (1 << (2 * x - 1));
dfs(x + 1, now * t, s);
t = t * a[x][0];
} else
break;
}
inline int ksm(int a, int b) {
int S = 1;
for (; b; b >>= 1, a = a * a)
if (b & 1)
S = S * a;
return S;
}
inline int qm(int x) { return x < 0 ? x + mod : x % mod; }
inline void Fwt(int *f, int o) {
for (re int i = 2; i <= len; i <<= 1)
for (re int ln = i >> 1, l = 0; l < len; l += i)
for (re int x = l; x < l + ln; ++x) f[x + ln] = qm(f[x + ln] + o * f[x]);
}
int main() {
N = read(), G = read(), L = read(), Q = read();
M = std::ceil(std::sqrt(L));
if (L % G) {
for (re int i = 1; i <= Q; i++) puts("0");
return 0;
}
for (re int i = 2; i <= M; i++) {
if (!f[i])
p[++p[0]] = i;
for (re int j = 1; j <= p[0] && p[j] * i <= M; j++) {
f[p[j] * i] = 1;
if (i % p[j] == 0)
break;
}
}
std::swap(G, L);
for (re int i = 1; i <= p[0]; i++) {
if (G % p[i])
continue;
a[++cnt[0]][0] = p[i];
while (G % p[i] == 0) G /= p[i], ++r[cnt[0]];
}
if (G > 1)
a[++cnt[0]][0] = G, r[cnt[0]] = 1;
for (re int i = 1; i <= p[0]; i++) {
if (L % p[i])
continue;
a[++cnt[1]][1] = p[i];
while (L % p[i] == 0) L /= p[i], ++b[cnt[1]];
}
if (L > 1)
a[++cnt[1]][1] = L, b[cnt[1]] = 1;
for (re int i = 1; i <= cnt[0]; i++)
for (re int j = 1; j <= cnt[1]; j++)
if (a[j][1] == a[i][0]) {
l[i] = b[j];
break;
}
for (re int i = 1; i <= cnt[0]; ++i) beg[i] = ksm(a[i][0], l[i]);
dfs(1, 1, 0);
for (re int i = 1; i <= n; i++) ma[c[i]] = i;
dp[0][0] = 1;
len = 1 << (2 * cnt[0]);
for (re int i = 1; i <= n; i++)
for (re int j = 0; j < len; j++) {
if (!dp[i - 1][j])
continue;
dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
dp[i][j | st[i]] = (dp[i][j | st[i]] + dp[i - 1][j]) % mod;
}
tp[n + 1][0] = 1;
for (re int i = n; i; --i)
for (re int j = 0; j < len; j++) {
if (!tp[i + 1][j])
continue;
tp[i][j] = (tp[i][j] + tp[i + 1][j]) % mod;
tp[i][j | st[i]] = (tp[i][j | st[i]] + tp[i + 1][j]) % mod;
}
while (Q--) {
int x = read(), pos = ma[x];
if (!pos) {
puts("0");
continue;
}
if (vis[pos]) {
printf("%d\n", ans[pos]);
continue;
}
Fwt(dp[pos - 1], 1), Fwt(tp[pos + 1], 1);
for (re int i = 0; i < len; i++) d[i] = 1ll * dp[pos - 1][i] * tp[pos + 1][i] % mod;
Fwt(d, -1);
for (re int i = 0; i < len; i++)
if ((i | st[pos]) + 1 == len)
ans[pos] = (ans[pos] + d[i]) % mod;
vis[pos] = 1;
printf("%d\n", ans[pos]);
}
return 0;
}

[SNOI2017]遗失的答案的更多相关文章

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

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

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

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

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

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

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

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

  5. bzoj 5019: [Snoi2017]遗失的答案【dp+FWT】

    满足GL的组合一定包含GL每个质因数最大次幂个最小次幂,并且能做限制这些数不会超过600个 然后质因数最多8个,所以可以状压f[s1][s2]为选s1集合满足最大限制选s2集合满足最小限制 dfs一下 ...

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

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

  7. LOJ2257 SNOI2017 遗失的答案 容斥、高维前缀和

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

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

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

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

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

随机推荐

  1. 【转载】WebRTC基于GCC的拥塞控制(上) - 算法分析

    实时流媒体应用的最大特点是实时性,而延迟是实时性的最大敌人.从媒体收发端来讲,媒体数据的处理速度是造成延迟的重要原因:而从传输角度来讲,网络拥塞则是造成延迟的最主要原因.网络拥塞可能造成数据包丢失,也 ...

  2. 【latex】latex基础

    文档边距.间距调整 边距调整 \usepackage{geometry} %设置页边距的宏包 \geometry{left=3.0cm,right=2.5cm,top=2.5cm,bottom=2.5 ...

  3. (转)简述负载均衡&CDN技术

    转:http://www.cnblogs.com/mokafamily/p/4402366.html#commentform 曾经见到知乎上有人问“为什么像facebook这类的网站需要上千个工程师维 ...

  4. opencv-图像形态学之开运算、闭运算、形态学梯度、顶帽、黑帽合辑

    转自:https://blog.csdn.net/poem_qianmo/article/details/24599073 1.1 开运算(Opening Operation) 开运算(Opening ...

  5. word 文献标题自动编号

    来自:word中自动编号和多级编号的使用 选中标题或段落,点击鼠标右键,在编号菜单内选择适合的自动编号样式.或者在窗口上方的“开始”选项卡中选择编号样式.如果对已选的编号样式不满意,可以照以上方法直接 ...

  6. AtCoder ABC 131E Friendships

    题目链接:https://atcoder.jp/contests/abc131/tasks/abc131_e 题目大意 给定 N 和 K,要求构造有 N 个点,恰有 K 对点,它们的最短距离为 2 的 ...

  7. 拾遗:Perl 正则表达式

    三种正则模式: 匹配:m//,其中前缀 m 可省略 替换:s/// 转化:tr/// 操作符: =~:存在匹配项则返回结果 !~:不存在匹配项则返回结果 修饰符: i:忽略大小写,如:s/.../.. ...

  8. 20140321 sizeof 虚函数与虚函数表 静态数组空间 动态数组空间 位字段

    1.静态的数组空间char a[10];sizeof 不能用于1:函数类型 2:动态的数组空间new3:位字段 函数类型:int fun();sizeof(fun())计算的是返回类型的大小,并不是函 ...

  9. Spring Boot 整合 Druid && 配置数据源监控

    1. 导入 Druid 包 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid& ...

  10. POJ 3525 /// 半平面交 模板

    题目大意: 给定n,接下来n行逆时针给定小岛的n个顶点 输出岛内离海最远的点与海的距离 半平面交模板题 将整个小岛视为由许多半平面围成 那么以相同的比例缩小这些半平面 一直到缩小到一个点时 那个点就是 ...