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. 支付宝携手HarmonyOS SDK打造高效便捷的扫码支付体验

    背景 在日常的购物转账.生活缴费等在线支付中,用户在正式拉起支付界面前,均需要至少经历一次"识别"+两次"寻找",即识别归属应用.寻找应用.寻找扫码入口,才能完 ...

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

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

  3. DDL-操作表

    1.查询表 查询当前数据库下所有表名称 show tables; 查询表结构 desc 表名称; 2.创建表 create table 表名 ( 字段名1 数据类型1, 字段名2 数据类型2, ... ...

  4. SpringMVC —— 响应

    响应页面    响应文本数据    响应json数据    响应json集合数据    注解      转换json时使用了类型转换器     

  5. 祝福 Eric 的下一段旅程,Flutter 3.3 现已发布

    Flutter 团队及社区成员们在美丽的城市挪威奥斯陆向您发来问候,我们正在此参加社区举办的 Flutter Vikings 活动,这是一个为期两天的开发技术交流盛会,虽然线下门票已经售罄,但您还可以 ...

  6. 支付宝 APP登录 获取用户信息 PHP(转)

    转载自:https://blog.csdn.net/wang78699425/article/details/78666401 支付宝 APP登录 获取用户信息 PHP(转) 支付宝APP登录服务端流 ...

  7. 对于ChannelNet的一点理解

    主要是为了个人理解,做个笔记 1.Pytorch代码 2.论文出处 3.详细介绍 这篇论文在2018年发出来,而ShuffleNet是从2017年由旷视发出来.起初了解shufflenet的提出,主要 ...

  8. 2022年第十八届 GOPS 全球运维大会资料分享

    全球运维大会是国内第一个运维行业大会,面向互联网.金融.通信及传统行业广大运维技术人员,旨在传播先进技术思想和理念,分享业内最佳实践. 2022年第十八届 GOPS 全球运维大会(深圳站)共分为18个 ...

  9. DDD实体和对象

    实体 entity 标识符用来唯一定位一个对象,在数据库中我们一般用表的主键来实现标识符,主键和标识符的思考角度不同,就是 id 字段 : 实体:拥有唯一的标识符,标识符的值不会改变,而其他对象的状态 ...

  10. 如何在 ubuntu 上搭建 minio

    由于腾讯的对象存储服务器(COS)的半年免费试用期已过,所以寻思鼓捣一下 minio,试着在自己的服务器上搭建一套开源的 minio 对象存储系统. 单机部署基本上有以下两种方式. 直接安装 最基础的 ...