Solution -「CF 804F」Fake bullions
\(\mathcal{Description}\)
Link.
给定 \(n\) 个点的竞赛图,第 \(i\) 个点代表了 \(s_i\) 个人,每个人(0-based)可能有真金条。此后在 \(t\) 时刻,对于图上任意边 \(\langle u,v\rangle\),若 \(u\) 中第 \(t\bmod s_u\) 个人有金条(无论真假),且 \(v\) 中第 \(t\bmod s_v\) 个人没有金条,那么后者获得一根假金条。
足够长的时间后,所有人开始卖金条。真金条必定能出售,假金条可能能出售。把每个点按其代表的人卖出的金条总数从大到小排序,再随机从前 \(A\) 名中选 \(B\) 个点,求这 \(B\) 个点能构成的集合数量。对 \(10^9+7\) 取模。
\(n\le5\times10^3\),\(\sum s_i\le2\times10^6\)。
\(\mathcal{Solution}\)
拼凑题嘛……和某道题一样过分 qwq。
第一个问题:每个点最终拥有多少假金条。
考虑一条边 \(\langle u,v\rangle\),显然若两人 \(x,y\) 在模 \(\gcd(s_u,s_v)\) 下同余,\(x\) 就能给 \(y\) 假金条。当然,金条的传递能够多次进行,所以可以缩点。对于第 \(i\) 个 SCC,计算出其中所有 \(s\) 的 \(\gcd\),记为 \(d_i\)。那么 SCC 中某个点的第 \(x\) 个人有金条,当且仅当存在一个与 \(x\) 在模 \(d_i\) 意义下同余的 \(y\) 有金条。考虑两个 SCC 的连边 \(\langle p,q\rangle\),本质上是和点的连边一样的。这样就能计算出每个点的假金条数量了。
接下来,考虑计算答案,每个点的售出金条对应了区间 \([l_u,r_u]\)。钦定一个集合 \(B\) 在其中售出金条最小(多个最小则钦定编号最小)的点处被计数,枚举最小区间 \([x,y]\),设有 \(p\) 个区间的 \([l,r]\) 满足 \(l>y\),它们是一定比当前区间大的;有 \(q\) 个区间 \([l,r]\) 满足 \(l\le y\le r\)(注意上述钦定编号的情况,这里没有体现),再枚举在 \(q\) 个区间里选 \(i\) 个,则贡献为:
\]
统计答案就好 w。
\(\mathcal{Code}\)
#pragma GCC optimize( 2 )
#include <cstdio>
#include <vector>
const int MAXN = 5e3, MAXL = 2e6, MOD = 1e9 + 7;
int n, s[MAXN + 5], A, B, mng[MAXN + 5], mxg[MAXN + 5];
int fac[MAXN + 5], ifac[MAXN + 5];
std::vector<int> adj[MAXN + 5];
std::vector<bool> gold[MAXN + 5];
int dfc, top, dfn[MAXN + 5], low[MAXN + 5], stk[MAXN + 5];
bool instk[MAXN + 5];
int scc, bel[MAXN + 5], siz[MAXN + 5], cnt[MAXN + 5];
std::vector<bool> apr[MAXN + 5];
int ans;
inline void chkmin ( int& a, const int b ) { if ( b < a ) a = b; }
inline int rint () {
int x = 0; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () );
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x;
}
inline int gcd ( const int a, const int b ) { return b ? gcd ( b, a % b ) : a; }
inline int qkpow ( int a, int b, const int p = MOD ) {
int ret = 1;
for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p;
return ret;
}
inline void Tarjan ( const int u ) {
dfn[u] = low[u] = ++ dfc, instk[stk[++ top] = u] = true;
for ( int v: adj[u] ) {
if ( ! dfn[v] ) {
Tarjan ( v );
chkmin ( low[u], low[v] );
} else if ( instk[v] ) {
chkmin ( low[u], dfn[v] );
}
}
if ( dfn[u] == low[u] ) {
int v; ++ scc;
do {
instk[v = stk[top --]] = false;
bel[v] = scc;
} while ( v ^ u );
}
}
inline void input () {
n = rint (), A = rint (), B = rint ();
char tmp[MAXL + 5];
for ( int i = 1; i <= n; ++ i ) {
scanf ( "%s", tmp + 1 );
for ( int j = 1; j <= n; ++ j ) {
if ( tmp[j] ^ '0' ) {
adj[i].push_back ( j );
}
}
}
for ( int i = 1; i <= n; ++ i ) {
gold[i].resize ( s[i] = rint () );
scanf ( "%s", tmp );
for ( int j = 0; j < s[i]; ++ j ) {
mng[i] += gold[i][j] = tmp[j] ^ '0';
}
}
}
inline void init () {
fac[0] = 1;
for ( int i = 1; i <= n; ++ i ) fac[i] = 1ll * i * fac[i - 1] % MOD;
ifac[n] = qkpow ( fac[n], MOD - 2 );
for ( int i = n - 1; ~ i; -- i ) ifac[i] = ( i + 1ll ) * ifac[i + 1] % MOD;
}
inline int comb ( const int n, const int m ) {
return n < m ? 0 : 1ll * fac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}
inline void calcBound () {
for ( int i = 1; i <= n; ++ i ) {
if ( ! dfn[i] ) {
Tarjan ( i );
}
}
for ( int i = 1; i <= n; ++ i ) siz[bel[i]] = gcd ( s[i], siz[bel[i]] );
for ( int i = 1; i <= scc; ++ i ) apr[i].resize ( siz[i] );
for ( int i = 1; i <= n; ++ i ) {
for ( int j = 0; j < s[i]; ++ j ) {
if ( gold[i][j] ) {
apr[bel[i]][j % siz[bel[i]]] = true;
}
}
}
std::vector<bool> tmp;
for ( int i = scc; i > 1; -- i ) {
int d = gcd ( siz[i], siz[i - 1] );
tmp.clear (), tmp.resize ( d );
for ( int j = 0; j < siz[i]; ++ j ) tmp[j % d] = tmp[j % d] | apr[i][j];
for ( int j = 0; j < siz[i - 1]; ++ j ) apr[i - 1][j] = apr[i - 1][j] | tmp[j % d];
}
for ( int i = 1; i <= scc; ++ i ) for ( bool g: apr[i] ) cnt[i] += g;
for ( int i = 1; i <= n; ++ i ) mxg[i] = s[i] / siz[bel[i]] * cnt[bel[i]];
}
inline void solve () {
for ( int i = 1; i <= n; ++ i ) {
int big = 0, crs = 0;
for ( int j = 1; j <= n; ++ j ) {
if ( i == j ) continue;
if ( mxg[i] < mng[j] ) ++ big;
else if ( mxg[i] <= mxg[j] - ( j < i ) ) ++ crs;
}
int l = std::max ( B - big - 1, 0 );
int r = std::min ( crs, std::min ( B - 1, A - big - 1 ) );
for ( int j = l; j <= r; ++ j ) {
ans = ( ans + 1ll * comb ( crs, j ) * comb ( big, B - j - 1 ) ) % MOD;
}
}
}
int main () {
input (), init ();
calcBound ();
solve ();
printf ( "%d\n", ans );
return 0;
}
Solution -「CF 804F」Fake bullions的更多相关文章
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
- Solution -「CF 1622F」Quadratic Set
\(\mathscr{Description}\) Link. 求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...
- Solution -「CF 923F」Public Service
\(\mathscr{Description}\) Link. 给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...
- Solution -「CF 923E」Perpetual Subtraction
\(\mathcal{Description}\) Link. 有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...
- Solution -「CF 1586F」Defender of Childhood Dreams
\(\mathcal{Description}\) Link. 定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...
- Solution -「CF 1237E」Balanced Binary Search Trees
\(\mathcal{Description}\) Link. 定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...
- Solution -「CF 623E」Transforming Sequence
题目 题意简述 link. 有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...
- Solution -「CF 1023F」Mobile Phone Network
\(\mathcal{Description}\) Link. 有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...
- Solution -「CF 599E」Sandy and Nuts
\(\mathcal{Description}\) Link. 指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...
随机推荐
- Jquery通过遍历数组给checkbox赋默认值
需求:有一个数组:(北京菜,粤菜),checkbox如下: 现在想通过遍历这个数组,使数组里包含的值,在checkbox选中 代码: var flavors = new Array([北京菜 , 粤菜 ...
- 创建react开发环境
准备工作 1.下载node.js(http://nodejs.cn/download/)推荐下载长期支持的版本 2.下载cnpm(https://jingyan.baidu.com/article/9 ...
- linux服务器之间传输文件的四种方式
linux文件传输在内网渗透中至关重要,所以我在此总结一下几种Linux服务器之间传输文件的四种方式 1. scp [优点]简单方便,安全可靠:支持限速参数[缺点]不支持排除目录[用法]scp就是se ...
- 读 Linux 像读小说「GitHub 热点速览 v.22.03」
本周特推选取了一个画风有点意思的 Linux 代码带读项目 flash-linux0.11-talk,希望有趣的文风能带你读完 Linux 代码.当然画风可以增加阅读体验,彩色标记也是一种学习方法-- ...
- tomcat容器启动失败疑难问题解决方案
严重: 子容器启动失败java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: 初始化组件[or ...
- 【机器学习】svm
机器学习算法--SVM 目录 机器学习算法--SVM 1. 背景 2. SVM推导 2.1 几何间隔和函数间隔 2.2 SVM原问题 2.3 SVM对偶问题 2.4 SMO算法 2.4.1 更新公式 ...
- Python中的路径
转义 windows路径使用的是\,linux路径使用的是/. 特别的,在windows系统中如果有这样的一个路径 D:\nxxx\txxx\x1,程序会报错.因为在路径中存在特殊符 \n(换行符)和 ...
- Web开发底层是Servlet
SpringMVC:是基于spring的一个框架,实际上就是spring的一个模块,专门是做web开发. 可以理解成servlet是一个升级 web开发底层是servlet,框架是在servlet基础 ...
- 用c#实现编写esp32单片机获取DHT11温度传感器参数
欢迎爱好c#的爱好者,本文章我们将用C#的nanoframework框架来编写获取esp32单片机上的DHT11传感器的温度和湿度 实现我们需要准备配置好esp32的环境可以看看之前写的esp32搭建 ...
- 近期Android学习II
一晃眼又过了5天,这几天的学习有些杂乱,半年在家没运动,返校了准备慢慢恢复运动,身体才是革命的本钱~ 四天跑了三回步,每次都死亡喘息= = 这几天的学习重点总归还是放在Android上了,前面31天连 ...