Codeforces 360D Levko and Sets (数论好题)
题意:有一个长度为n的数组a和一个长度为m的数组b,一个素数p。有n个集合,初始都只有一个1。现在,对(i从1到n)第i个集合执行以下操作:
对所有集合中的元素c,把c * (a[i] ^ b[j]) mod p 加入集合(j从1到m), 直到集合的元素不再增加为止。
问最后这n个集合的并有多少个元素?
n到1e4, m到1e5, p到1e9。
思路(官方题解)这题运用了很多数论的知识,不对数论有一定了解比较难做出这道题。
涉及的知识:原根,阶,欧拉定理,贝祖定理。
首先我们知道,x ^ y mod p = x ^ (y mod phi(p)) mod p(欧拉定理),而集合的操作可以看成a的指数相加,所以我们第一步先求出所有b和p - 1的gcd = t,这样每个集合的大小是(p - 1) / t,(贝祖定理),集合中的元素为a[i] ^ (k * t)。但是,由于a是不一定相同的,所以我们很难直接合并。我们可以转化成原根的形式,那么假设g ^ (r[i]) = a[i], ,令q[i] = gcd(r[i], p - 1)(贝祖定理)。我们不妨令g = g ^ t,因为t是一个常数。那么,现在集合中的元素为g ^ (q[i] * k), 我们现在需要求出q[i]。怎么求q[i]呢?我们只要求出a[i] ^ t的阶 = l,然后(p - 1) / l就是q[i], 为什么呢?因为(a[i] ^ t) ^ l mod p = 1 mod p = g ^ (p - 1) mod p => a[i] ^ t mod p= g ^ ((p - 1) / l) mod p, 这样就可以算出对应的q[i],即a[i] ^ t的原根中的指标。现在我们求出了q[i],那么所有g ^ (q[i] * k)会出现在集合中。一种想法是用筛法,但是p很大,不能筛。这里需要用到容斥原理。
注意,cf上很多代码的容斥是假的,可以被hack。
以下是来自cf评论区的两个数据:
2 1 13
3 5
1
答案:6
2 1 37
31 27
1
答案:8
正确容斥做法:先处理出p - 1的所有因子,从大到小枚举,枚举因子时判断是否有q[i],始得这个因子是q[i]的倍数,如果有,说明这个因子可以对答案产生贡献,再枚举比它大的因子,如果有因子是这个因子的倍数,那么减去这个因子的贡献。最后剩下的是这个因子的贡献。如果没有,跳过即可。均摊的复杂度应该是O(log ^ 2(p))。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 100010;
int n, m, p;
int a[maxn], b[maxn], q[maxn], dp[maxn];
int qpow(int x, int y) {
int ans = 1;
for (; y; y >>= 1) {
if(y & 1) ans = ((LL)ans * x) % p;
x = ((LL)x * x) % p;
}
return ans;
}
vector<int> re;
void div(int x) {
for (int i = 1; i * i <= x; i++) {
if(x % i == 0) {
re.push_back(i);
if(i * i != x)
re.push_back(x / i);
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &p);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
int t = p - 1;
for (int i = 1; i <= m; i++) {
scanf("%d", &b[i]);
t = __gcd(t, b[i]);
}
div(p - 1);
sort(re.begin(), re.end());
for (int i = 1; i <= n; i++) {
a[i] = qpow(a[i], t);
for (int j = 0; j < re.size(); j++) {
if(qpow(a[i], re[j]) == 1) {
q[i] = (p - 1) / re[j];
break;
}
}
}
sort(q + 1, q + 1 + n);
n = unique(q + 1, q + 1 + n) - (q + 1);
int ans = 0;
for (int j = re.size() - 1; j >= 0; j--) {
bool flag = 0;
for (int i = 1; i <= n; i++) {
if(re[j] % q[i] == 0) {
flag = 1;
for (int k = j + 1; k < re.size(); k++) {
if(re[k] % re[j] == 0)
dp[j] -= dp[k];
}
break;
}
}
if(flag) {
dp[j] += (p - 1) / re[j];
ans += dp[j];
}
}
printf("%d\n", ans);
}
Codeforces 360D Levko and Sets (数论好题)的更多相关文章
- [CodeForces - 1225D]Power Products 【数论】 【分解质因数】
[CodeForces - 1225D]Power Products [数论] [分解质因数] 标签:题解 codeforces题解 数论 题目描述 Time limit 2000 ms Memory ...
- Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论
Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变 ...
- Codeforces Round #609 (Div. 2)前五题题解
Codeforces Round #609 (Div. 2)前五题题解 补题补题…… C题写挂了好几个次,最后一题看了好久题解才懂……我太迟钝了…… 然后因为longlong调了半个小时…… A.Eq ...
- Codeforces 515C 题解(贪心+数论)(思维题)
题面 传送门:http://codeforces.com/problemset/problem/515/C Drazil is playing a math game with Varda. Let’ ...
- Codeforces 571E - Geometric Progressions(数论+阿巴细节题)
Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉此题思维难度不太大,不过大概是细节多得到了精神污染的地步所以才放到 D1E 的罢((( 首先我们对所有 \(a_i,b_i\ ...
- Coprime Arrays CodeForces - 915G (数论水题)
反演一下可以得到$b_i=\sum\limits_{d=1}^i{\mu(i)(\lfloor \frac{i}{d} \rfloor})^n$ 整除分块的话会T, 可以维护一个差分, 优化到$O(n ...
- [BZOJ1951][SDOI2005]古代猪文(数论好题)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1951 分析: 练习数论知识的好题,涉及到费马小定理.lucas定理.求逆元
- Educational Codeforces Round 7 B. The Time 水题
B. The Time 题目连接: http://www.codeforces.com/contest/622/problem/B Description You are given the curr ...
- Educational Codeforces Round 7 A. Infinite Sequence 水题
A. Infinite Sequence 题目连接: http://www.codeforces.com/contest/622/problem/A Description Consider the ...
随机推荐
- HTML5:新元素来实现一下网页布局
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- bzoj3812 主旋律 容斥+状压 DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3812 题解 考虑对于图的联通性的 DP 的一般套路:总方案 - 不连通的方案. 那么我们只需要 ...
- jsonp跨域获取数据实现百度搜索
本菜鸡最近在写某个页面请求数据时,报了如下的错误. Failed to load https://...:No 'Access-Control-Allow-Origin' header is pres ...
- FMXUI TEXTVIEW代码设置IMAGEINDEX
FMXUI作为一个开源的控件,真是DELPHIER的福音,向作者致敬.TEXTVIEW非常好用,在属性面板中有ImageIndex属性,可以方便设置图标,在实际应用中图标状态需要改变,但在代码设置时 ...
- 编写现代 CSS 代码的 20 个建议
明白何谓Margin Collapse 不同于其他很多属性,盒模型中垂直方向上的Margin会在相遇时发生崩塌,也就是说当某个元素的底部Margin与另一个元素的顶部Margin相邻时,只有二者中的较 ...
- 早日选择一门自己喜欢的,然后瞄准目标,不达目的誓不罢休。像文章的作者一样成为一名成功的IT人士。
hawk的奋斗历程. 来自:LinuxForum :http://www3.linuxforum.net/ 原址:http://www.linuxforum.net/forum/gshowflat. ...
- C# 实现软件注册功能
相信很多初学编程的人都会对这个注册功能很感兴趣,我也不例外,刚学asp.net时,竞找不到这方面的实例,结果自己参考微软的一些文档自己做了一个,其实我做的这个注册功能很简单,读取计算机的CPU序列号, ...
- CVE-2017-0213 | 记一次失败的提权经历
环境: CVE-2017-0213下载 提权步骤: 提权失败.... 好迷啊,,,,事后查了一下补丁 我的wind7上也没装啊,然后防火墙也是关闭的 迷了迷了....
- 2-prometheus各组件安装
相关下载: https://prometheus.io/download/https://github.com/prometheus/ 相关文档 https://songjiayang.gitbook ...
- python中的open()函数
定义: python open() 函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写 参数: 模式 描述 r 以只读方式打开文件.文件的指针将会放在文件的开头.这是默认模 ...