Solution:

​ 这题可以分为两个部分,

​ 一个部分为处理出每个点最大的金条数与最小的金条数,记为 \([Min_i, Max_i]\)

​ 第二部分为对于 \(n\) 个变量 \(x_i\in[Min_i, Max_i]\cup \mathbb {Z}\),计算选出 \(B\) 个前 \(A\) 大变量的方案数。

​ 对于两个点 u->v ,如果有 u 的人 i (有金条)v 的人 j 满足 \(i\equiv j(\text{mod }\gcd(S_u, S_v))\) ,那么 i 就可以给 j 假金条。

​ 同理,对于一条路径 u->...->vg 为其 \(\gcd\) ,那么只要满足 \(i \equiv j(\text{mod }g)\) ,那么 i 就可以给 j 假金条。

​ 所以对于一个强连通分量中,有金条的人就会满足 \(i\equiv j(\text{mod } g)\) ,j 为每个点有金条的人,g为整个强连通分量的 \(\gcd\) 。

​ 枚举一个点有金条的人,这样就可以 \(O(\text{金条数目})\) 求出每一个强连通分量的金条拥有状态。

​ 由竞赛图的性质,缩点后的竞赛图还是竞赛图,而且会长这个样子:

​ 即每个点都向它后面连边,显然我们为了让金条数量最大化就是按照拓扑序依次算点的贡献,这样算出来每个强连通分量的金条数假设为 Mx 那么每个点u拥有的金条数就是\(\frac{S_uMx}{g}\)。

​ 接下来就考虑怎么计数,为了不算重,枚举 u 为B中最小的点,然后统计出 \(Max_u<Min_i\) 的数量 \(cnt_1\),以及 \(Max_i\geq Max_u\geq Min_i\) 的数量 \(cnt_2\),那么再枚举在 \(cnt_2\)个中选j个,给答案加上 \({~cnt_2~\choose j}{~cnt_1~\choose B - 1 - j}\)。

#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
#include <vector>
#define LL long long
using namespace std;
const int maxn = 5003;
const int MOD = 1e9 + 7;
vector<int> g[maxn];
vector<bool> city[maxn];
int A, B, n;
int s[maxn], fac[maxn], ifac[maxn];
void input() {
char str[(int)(2e6) + 2];
scanf("%d %d %d", &n, &A, &B);
for (int i = 1; i <= n; ++i) {
scanf("%s", str + 1);
for (int j = 1; j <= n; ++j)
if (str[j] == '1')
g[i].push_back(j);
}
for (int i = 1; i <= n; ++i) {
scanf("%d %s", &s[i], str);
city[i].resize(s[i]);
for (int j = 0; j < s[i]; ++j)
city[i][j] = str[j] - '0';
}
}
LL qpow(LL a, LL b) {
LL res(1);
while (b) {
if (b & 1) {
res = res * a % MOD;
}
a = a * a % MOD;
b >>= 1;
}
return res;
}
void init() {
fac[0] = 1;
int N = maxn - 3;
for (int i = 1; i <= N; ++i)
fac[i] = 1ll * fac[i - 1] * i % MOD;
ifac[N] = qpow(fac[N], MOD - 2);
for (int i = N - 1; i >= 0; --i)
ifac[i] = 1ll * ifac[i + 1] * (i + 1) % MOD;
}
vector<bool> colbull[maxn];
int Gcdcol[maxn], cntbull[maxn], maxbull[maxn], minbull[maxn];
int low[maxn], dfn[maxn], dfst, col[maxn], colcnt, stk[maxn], top;
void tarjan(int u) {
dfn[u] = low[u] = ++dfst;
stk[++top] = u;
for (int i = 0; i < (int)g[u].size(); ++i) {
int v= g[u][i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (!col[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
++colcnt;
int v;
do {
v = stk[top--];
col[v] = colcnt;
} while (u != v);
Gcdcol[colcnt] = s[u];
}
}
void solve1() {
for (int i = 1; i <= n; ++i)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= n; ++i)
Gcdcol[col[i]] = __gcd(Gcdcol[col[i]], s[i]);
for (int i = 1; i <= n; ++i) {
colbull[col[i]].resize(Gcdcol[col[i]]);
for (int j = 0; j < s[i]; ++j)
if (city[i][j] == 1) {
colbull[col[i]][j % Gcdcol[col[i]]] = 1;
}
}
vector<bool> tmp;
for (int i = colcnt; i >= 2; --i) {
int g = __gcd(Gcdcol[i], Gcdcol[i - 1]);
tmp.clear();
tmp.resize(g);
for (int j = 0; j < Gcdcol[i]; ++j)
tmp[j % g] = tmp[j % g] | colbull[i][j];
for (int j = 0; j < Gcdcol[i - 1]; ++j)
colbull[i - 1][j] = colbull[i - 1][j] | tmp[j % g];
}
for (int i = 1; i <= colcnt; ++i)
for (int j = 0; j < Gcdcol[i]; ++j)
cntbull[i] += colbull[i][j];
for (int i = 1; i <= n; ++i)
maxbull[i] = s[i] / Gcdcol[col[i]] * cntbull[col[i]];
for (int i = 1; i <= n; ++i)
for (int j = 0; j < s[i]; ++j)
minbull[i] += city[i][j];
}
LL ans;
LL combine(int n, int m) {
if (m < 0 || n < 0 || m > n) return 0;
return 1ll * fac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}
void solve2() {
for (int i = 1; i <= n; ++i) {
int cnt1 = 0, cnt2 = 0;
for (int j = 1; j <= n; ++j) {
if (i == j) continue;
if (minbull[j] > maxbull[i]) ++cnt1;
else if (maxbull[j] > maxbull[i] || (maxbull[j] == maxbull[i] and j < i)) ++cnt2;
}
if (cnt1 >= A) continue;
for (int j = min(B - 1, min(cnt2, A - 1 - cnt1)); j >= B - cnt1 - 1 && j >= 0; j--) {
ans = (1ll * ans + 1ll * combine(cnt1, B - j - 1) * combine(cnt2, j) % MOD) % MOD;
}
}
cout << ans << endl;
}
int main() {
// freopen("fake.in", "r", stdin);
// freopen("fake.out", "w", stdout);
input();
init();
solve1();
solve2();
return 0;
}

[CF804F]Fake bullions的更多相关文章

  1. [codeforces 804F. Fake bullions]

    题目大意: 传送门. 给一个n个点的有向完全图(即任意两点有且仅有一条有向边). 每一个点上有$S_i$个人,开始时其中有些人有真金块,有些人没有金块.当时刻$i$时,若$u$到$v$有边,若$u$中 ...

  2. 【Codeforces】【图论】【数量】【哈密顿路径】Fake bullions (CodeForces - 804F)

    题意 有n个黑帮(gang),每个黑帮有siz[i]个人,黑帮与黑帮之间有有向边,并形成了一个竞赛完全图(即去除方向后正好为一个无向完全图).在很多年前,有一些人参与了一次大型抢劫,参与抢劫的人都获得 ...

  3. Solution -「CF 804F」Fake bullions

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点的竞赛图,第 \(i\) 个点代表了 \(s_i\) 个人,每个人(0-based)可能有真金条.此后在 ...

  4. Fake chat script for website download

    Are you searching for free fake webchat script then you are at the right place go get download your ...

  5. fake gucci outlet perform a couple associated with things in great trust

    Based on my a lot of years of encounter within Taobao, purchase bags must go to the high reputation ...

  6. Zyxel Switch-How to block a fake DHCP server without enabling DHCP snooping?

    How to block a fake DHCP server without enabling DHCP snooping? Scenario How to block a fake DHCP se ...

  7. Codeforces Round #310 (Div. 2) B. Case of Fake Numbers 水题

    B. Case of Fake Numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  8. 在使用Fake framework的时候,为什么有一些函数没有生产mock呢?

    在使用Visual studio 2012 的Fake framework 做单元测试的时候,你会发现有一些函数没有生产Stub 或者 Shim的版本,这可能是由于Fake的一些限制导致的,但如何知道 ...

  9. fake it till you become it

    fake it till you become it_你泛起山川烟波里的不是我._百度空间 fake it till you become it

随机推荐

  1. ORACLE之字符集修改(10g)

    当从oracle服务器将数据导出成dmp文件后,再导入到本地的oracle数据库时,出现: IMP-00019: 由于 ORACLE 错误 12899 而拒绝行 IMP-00003: 遇到 ORACL ...

  2. JavaScript、ES6中类的this指向问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. TensorFlow 安装及使用

    安装 (1)安装包安装:pip install tensorflow==1.14 -i https://pypi.douban.com/simple virtualenv -p /usr/bin/py ...

  4. Java集合(容器)学习

    1.集合和数组有什么区别,为什么使用集合而不用数组? 相同点:集合和数组都可以存储多个对象,对外作为一个整体存在. 数组的缺点: 长度必须在初始化时指定,且固定不变: 数组采用连续存储空间,删除和添加 ...

  5. 英语单词character

    来源——tr帮助说明 TR() User Commands TR() NAME tr - translate or delete characters SYNOPSIS tr [OPTION]... ...

  6. python线程池示例

    使用with方式创建线程池,任务执行完毕之后,会自动关闭资源 , 否则就需要手动关闭线程池资源  import threading, time from concurrent.futures impo ...

  7. python学习笔记(八)函数return多个值,列表推导式和交换两个变量的值

    函数return多个值: 补充知识点:写代码得到时候少用全局变量: 1.不安全 2.会一直占着内存不释放 函数多个return值,那么会把这几个return的值都放在一个元组里面,然后返回 def h ...

  8. ubuntu 18.04下Chromium设置为系统代理

    前言 在ubuntu 18.04下挂上ss后firefox能直接上google了但是chromium上不去 会出现下面两种情况 # This site can't be reached xxxxxx ...

  9. [CF1166C]A Tale of Two Lands题解

    比赛的时候lowerbound用错了 现场WA on test4(好吧我承认我那份代码确实有除了lowerbound以外的问题) 于是只能手动二分 (我好菜啊QAQ 经过一波数学推算,我们发现,设序列 ...

  10. BUUCTF |[0CTF 2016]piapiapia

    步骤: nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere ...