博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bzoj5019: [Snoi2017]遗失的答案
阅读量:6838 次
发布时间:2019-06-26

本文共 3360 字,大约阅读时间需要 11 分钟。

\(L\) 唯一分解为 \(p_1^{a_1}p_2^{a_2}...p_k^{a_k}\)

对 G 也分解为 \(p_1^{b_1}p_2^{b_2}...p_k^{b_k}\)
\(a_i , b_i\) 分别为 \(p_i\) 这个质因子幂次的上下界。
显然为了满足 \(gcd\)\(G\)\(lcm\)\(L\),对于每一个 \(p_i\) ,就至少要
有一个数触其上界,有一个数触其下界。
那么就可以拿一个长为 \(2^k\) 的二进制状态表示每个质因子是否已
触其上界,是否已触其下界。
然后前后缀对于 \(L\) 的约数且是 \(G\) 的倍数的数作一遍 \(DP\)
直接 \(FWT\) 合并成为答案
还有更加优秀的容斥做法
首先问题已经转化为给定一些集合,求出或为全集的方案数
\(f_s\) 表示或为 \(s\) 的方案数
直接求不方便
\(g_s=\sum_{i\subset s}f_i\) 表示或为 \(s\) 的子集的方案数
那么 \(g_s=2^{cnt_s}-1\)(\(cnt_s\) 表示 \(s\) 的子集个数)
那么容斥得到 \(f_s=\sum_{i\subset s}(-1)^{|s|-|i|}g_i\)
对于钦定了一定要选集合 \(x\),只需要把 \(x\) 的超集 \(-1\) 然后再次做上面的容斥
记得 \(g_s=2^{cnt_s-1}\)

# include 
using namespace std;typedef long long ll; namespace IO { const int maxn(1 << 21 | 1); char ibuf[maxn], *iS, *iT, c; int f; inline char Getc() { return iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, maxn, stdin), (iS == iT ? EOF : *iS++)) : *iS++; } template
inline void In(Int &x) { for (f = 1, c = Getc(); c < '0' || c > '9'; c = Getc()) f = c == '-' ? -1 : 1; for (x = 0; c >= '0' && c <= '9'; c = Getc()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; }} using IO :: In; const int maxn(805);const int maxm(16);const int mod(1e9 + 7); int n, g, l, bl, q, p[maxm], mx[maxm], mn[maxm], tot, st, cnt;int size[1 << maxm], ans[maxn], pw[1 << maxm], bit[1 << maxm]; struct Fac { int x, y; inline bool operator <(Fac b) const { return x < b.x; }} a[maxn]; inline void Inc(int &x, int y) { x += y; if (x >= mod) x -= mod;} inline void Pre_Work(int x) { if (x > n || x % g) return; register int i, v; a[++cnt].x = x; for (i = 0; i < tot; ++i) { v = 0; while (x % p[i] == 0) x /= p[i], ++v; if (v == mn[i]) a[cnt].y |= 1 << i; if (v == mx[i]) a[cnt].y |= 1 << (i + tot); }} int main() { In(n), In(g), In(l), In(q); register int qq, i, j, x, y, k, tp; if (l % g) { for (qq = 1; qq <= q; ++qq) puts("0"); return 0; } x = l; for (i = 2; i * i <= x; ++i) if (x % i == 0) { while (x % i == 0) x /= i; p[tot++] = i; } if (x > 1) p[tot++] = x; st = 1 << (tot << 1), x = g, y = l; for (i = 0; i < tot; ++i) { while (x % p[i] == 0) x /= p[i], ++mn[i]; while (y % p[i] == 0) y /= p[i], ++mx[i]; } for (i = 1; i * i <= l; ++i) if (l % i == 0) { Pre_Work(i); if (i * i != l) Pre_Work(l / i); } sort(a + 1, a + cnt + 1); for (i = 1; i <= cnt; ++i) ++size[a[i].y]; for (i = 1; i < st; i <<= 1) for (tp = i << 1, j = 0; j < st; j += tp) for (k = 0; k < i; ++k) size[j + k + i] += size[j + k]; for (pw[0] = 1, j = size[st - 1], i = 1; i <= j; ++i) pw[i] = (pw[i - 1] + pw[i - 1]) % mod; for (i = 1; i < st; ++i) bit[i] = bit[i >> 1] + (i & 1); for (i = 1; i <= cnt; ++i) for (j = 0; j < st; ++j) if ((a[i].y & j) == a[i].y) Inc(ans[i], (bit[(st - 1) ^ j] & 1) ? mod - pw[size[j] - 1] : pw[size[j] - 1]); for (qq = 1; qq <= q; ++qq) { In(x); if (l % x || x % g) puts("0"); else { y = lower_bound(a + 1, a + cnt + 1, (Fac){x, 0}) - a; a[y].x != x ? puts("0") : printf("%d\n", ans[y]); } } return 0;}

转载于:https://www.cnblogs.com/cjoieryl/p/9896157.html

你可能感兴趣的文章
Eclipse常见问题集锦
查看>>
杭电 1711 Number Sequence 1686 2203
查看>>
石大ACM2587解题报告
查看>>
php 商场收银收费系统,使用的策略模式
查看>>
2016年宜昌楼市将迎来史上最激烈一战
查看>>
第一次团队冲刺4
查看>>
冒泡排序
查看>>
android studio 各种问题
查看>>
ios中一个开发者证书如何创建多个app应用
查看>>
创建和存储 cookie
查看>>
BZOJ2351[BeiJing2011]Matrix——二维hash
查看>>
Redis常用命令整理
查看>>
js的水仙花数的输出
查看>>
Codeforces Gym 100269 Dwarf Tower (最短路)
查看>>
mongo explain分析详解
查看>>
MySQL 行子查询
查看>>
Comparison Operators Modified by ANY, SOME, or ALL
查看>>
java第四次作业
查看>>
一台机器同时启动两个tomcat
查看>>
Determine destination location of apt-get install <package>?
查看>>