Flatten

给定\(n\)个正整数\(a_i\),,现在让你求出\(n\)个整数\(b_i\),使得任取\(1\le i < j \le n\),\(a_ib_i=a_jb_j\)始终成立,请你求出\(\sum b_i\)的最小值,答案对\(1e9+7\)取模

\(1\le n \le 10^4\)

\(1 \le a_i \le 10^6\)

题解:最大公倍数取模 + 质因数分解 + 快速幂求乘法逆元

  • 容易得到\(a_ib_i = lcm(\sum a_i)\),那么我们现在只要求出\(n\)个\(a_i\)的最大公倍数\(lcm\)且对\(1e9+7\)取模的结果,答案即为
\[\sum_{i=1}^{n}\frac{lcm}{a_i}
\]
  • 答案中存在除法,但是取模中没有除法,所以我们需要利用快速幂求出\(a_i\)在模\(1e9+7\)下的乘法逆元\(a_i^{-1}\),答案为
\[\sum_{i=1}^{n}lcm*a_i^{-1}
\]
  • 现在我们还需要解决最大公倍数取模的问题:

我们对每个\(a_i\)进行质因子分解,取每个质因子中的最大幂次作为最大公倍数的对应质因子的幂次,然后利用快速幂求出最大公倍数对\(1e9+7\)取模的结果

  • 时间复杂度:质因子分解\(O(\sqrt a_i)\),一共\(n\)个数,\(O(n\sqrt a_i)\),最终时间复杂度为\(O(n\sqrt a_i + nlog(1e9))\)
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e6 + 10, M = 4e5 + 10; int n;
int a[N];
int p[N], idx;
bool vis[N];
unordered_map<int, int> mp2; int qpow(int a, int b, int p)
{
int res = 1;
while (b)
{
if (b & 1)
res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res % p;
} void solve()
{
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
int t = a[i];
unordered_map<int, int> mp;
for (int j = 2; j <= t / j; ++j)
{
while (t % j == 0)
{
mp[j]++;
mp2[j] = max(mp2[j], mp[j]);
t /= j;
}
}
if (t > 1)
{
mp[t]++;
mp2[t] = max(mp2[t], mp[t]);
}
}
int d = 1;
for (auto [x, y] : mp2)
{
d = d * qpow(x, y, mod) % mod;
}
int ans = 0;
for (int i = 1; i <= n; ++i)
ans = (ans % mod + (d % mod * qpow(a[i], mod - 2, mod)) % mod) % mod;
cout << ans << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

Tree and Constraints

给你一颗有\(n\)个节点的树,你要给这棵树黑白染色,并且符合\(m\)条限制,每条限制给定\(u\)和\(v\),需要满足\(u\)到\(v\)的路径上至少有一个黑色边,问有多少种染色方案

\(2≤n≤50\)

\(1≤m≤min(20,2n(n−1))\)

题解:容斥原理 + 状压 + 树上异或 \(O(2^mm)\)

  • 首先染色总方案数\(S\)为\(2^{n-1}\),设\(A_i\)为满足第\(i\)个限制条件的合法方案数,题目想让我们求出\(\bigcap_{i=1}^{m}A_i\),即所有限制条件合法方案数的交集,但是比较难求,正难则反,我们不妨从反面考虑该答案:

设\(\bar{A_i}\)为不满足第\(i\)个限制条件的不合法方案数,那么我们把题目想让我们求的答案可以转化为

\[S-\bigcup_{i-1}^{m}\bar{A_i}
\]

因为\(m\le 20\),容易发现我们可以利用容斥原理求出\(\bigcup_{i-1}^{m}\bar{A_i}\) ,时间复杂度为:\(O(2^mm)\)

  • 那么现在我们要做的就是求出\(\bar{A_i}\),那么我们分析一下:

对于不满足\(u\)和\(v\)的限制条件的方案数\(\bar{A_i}\),只要\(u\)和\(v\)之间的所有边都涂成白色,那么其他不在\(u\)和\(v\)之间的边,颜色就可以随便涂,设\(u\)和\(v\)之间的边数为\(cnt\),那么

\[\bar{A_i} = 2^{n-1-cnt}
\]
  • 我们已经知道了\(\bar{A_i}\)怎么求,只要知道\(u\)和\(v\)之间的边数即可,但是我们在进行容斥的时候我们需要求出多个不合法方案之间的交集,那么交集就意味着我们涂的方案需要使得多个限制条件同时无法满足,即我们需要将所有限制条件里的边都涂成白色,所以说我们需要知道多个限制条件中边的并集,也就是说我们需要知道每个限制条件\(u\)和\(v\)之间的边具体有哪些边,我们考虑如何解决这个问题:

    因为\(n \le 50\),所以我们不妨将每个点到根节点的路径中边的状态利用二进制压缩,我们设点\(u\)到根节点的路径中边的状态为\(path_u\),我们设第\(i\)个限制条件\((u,v)\)之间边的信息为\(info_i\),利用树上异或的性质:
\[info_{i} = path_u \bigoplus path_v
\]

我们可以求出\(u\)和\(v\)之间有哪些边存在

  • 对于多个限制条件中边的并集的状态\(num\)为
\[\sum num\ \ |= \ \ info_i
\]
  • 设状态\(num\)中\(1\)的数量为\(cnt\)(即边的数量),那么对于不满足多个限制条件的方案的交集为
\[2^{n-1-cnt}
\]
  • 最后利用容斥原理解题即可
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 50 + 10, M = 4e5 + 10; int n, m;
vector<int> g[N];
int path[N];
int info[N]; void dfs(int u, int par)
{
path[u] = path[par] | (1ll << u);
for (auto v : g[u])
{
if (v == par)
continue;
dfs(v, u);
}
} void solve()
{
cin >> n;
for (int i = 1, u, v; i < n; ++i)
{
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
cin >> m;
for (int i = 0, u, v; i < m; ++i)
{
cin >> u >> v;
info[i] = path[u] ^ path[v];
}
int ans = 0;
for (int i = 1; i < (1 << m); ++i)
{
int cnt = 0;
int num = 0;
for (int j = 0; j < m; ++j)
{
if (i >> j & 1)
{
cnt++;
num |= info[j];
}
}
int free = n - 1 - __builtin_popcountll(num);
if (cnt % 2 == 1)
ans += (1ll << free);
else
ans -= (1ll << free);
}
cout << (1ll << (n - 1)) - ans << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
// cin >> T;
while (T--)
{
solve();
}
return 0;
}

AtCoder Beginner Contest 152的更多相关文章

  1. AtCoder Beginner Contest 100 2018/06/16

    A - Happy Birthday! Time limit : 2sec / Memory limit : 1000MB Score: 100 points Problem Statement E8 ...

  2. AtCoder Beginner Contest 052

    没看到Beginner,然后就做啊做,发现A,B太简单了...然后想想做完算了..没想到C卡了一下,然后还是做出来了.D的话瞎想了一下,然后感觉也没问题.假装all kill.2333 AtCoder ...

  3. AtCoder Beginner Contest 053 ABCD题

    A - ABC/ARC Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Smeke has ...

  4. AtCoder Beginner Contest 136

    AtCoder Beginner Contest 136 题目链接 A - +-x 直接取\(max\)即可. Code #include <bits/stdc++.h> using na ...

  5. AtCoder Beginner Contest 137 F

    AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...

  6. AtCoder Beginner Contest 076

    A - Rating Goal Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Takaha ...

  7. AtCoder Beginner Contest 079 D - Wall【Warshall Floyd algorithm】

    AtCoder Beginner Contest 079 D - Wall Warshall Floyd 最短路....先枚举 k #include<iostream> #include& ...

  8. AtCoder Beginner Contest 064 D - Insertion

    AtCoder Beginner Contest 064 D - Insertion Problem Statement You are given a string S of length N co ...

  9. AtCoder Beginner Contest 075 D - Axis-Parallel Rectangle【暴力】

    AtCoder Beginner Contest 075 D - Axis-Parallel Rectangle 我要崩溃,当时还以为是需要什么离散化的,原来是暴力,特么五层循环....我自己写怎么都 ...

  10. AtCoder Beginner Contest 075 C bridge【图论求桥】

    AtCoder Beginner Contest 075 C bridge 桥就是指图中这样的边,删除它以后整个图不连通.本题就是求桥个数的裸题. dfn[u]指在dfs中搜索到u节点的次序值,low ...

随机推荐

  1. 工具 – Cypress

    介绍 Cypress 是一款 e2e 测试工具.每当我们写好一个组件或者一个页面之后,我们会想对整体做一个测试. 在不使用工具的情况下,我们会开启 browser,然后做一系列点击.滚动.填 form ...

  2. HTML – W3Schools 学习笔记

    有用链接: HTML Attribute Reference (查看所有 Attributes) HTML Paragraphs Link to W3Schools <p> 里面 doub ...

  3. 十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明)

    十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明) @ 目录 十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明) 1. 基本介绍 2. 准备工作 3. ...

  4. RAG+Agent人工智能平台:RAGflow实现GraphRA知识库问答,打造极致多模态问答与AI编排流体验

    RAG+Agent人工智能平台:RAGflow实现GraphRA知识库问答,打造极致多模态问答与AI编排流体验 1.RAGflow简介 最近更新: 2024-09-13 增加知识库问答搜索模式. 20 ...

  5. WebRTC 初探

    背景 我正在实现一个 FC 游戏网站, PC 用户仅需要配置键盘便能实现小伙伴们一起玩, 但是手机用户就比较麻烦了 传统的网页游戏都是通过 HTTP/WS 的方式实现联机, 对于服务器的负担还是比较重 ...

  6. Nuke导出视频缺失 H.246格式 的解决办法

    同事在使用Nuke导出视频时报错,报错提示:缺失 H.246格式 后来经过我的研究发现,Quicktime Player 在标准安装时,默认不关联一些格式(具体是哪些格式不清楚) Quicktime ...

  7. ASP.NET Core OData 9的发布,放弃 .NET Framework

    Microsoft 于 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9 包. 这个新包将ASP.NET Core与.NET 8 OData库保持一致,改变了OData ...

  8. USB type-c CC管脚如何做到正反接检测功能

    USB Type-C 连接器的 CC (Configuration Channel) 管脚用于实现插头方向检测和电源管理.具体来说,USB Type-C 连接器具有两个 CC 管脚:CC1 和 CC2 ...

  9. linux中透明巨页与巨页的区别

    在Linux中,透明巨页(Transparent HugePage)和巨页(HugePage)是两种不同的内存管理技术. 透明巨页是Linux内核中的一项特性,旨在提高内存的利用率和性能.它通过将内存 ...

  10. vi指令总结

    VI常用技巧 ​ VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需要掌握基本命令,然后加以灵活运用,就会发现它的优势,并会逐 ...