【做题】SRM704 Div1 Median - ModEquation——数论
原文链接 https://www.cnblogs.com/cly-none/p/SRM704Div1B.html
给出\(n\)和模数\(P\)。\(q\)次询问,每次给出一个\([0,P-1]\)范围内的整数\(v\),求有多少长度为\(n\)的序列\(\{x\}\)满足\(x_i\)都是\([0,P-1]\)范围内的整数且\(\prod x_i \equiv v \pmod P\),答案对\(10^9 + 7\)取模。
\(n \leq 50 , \ q \leq 10^3, \ P \leq 10^9\)
注意:\(P\)不是质数。
这题大概就是道结论题。
首先,我们容易得到\(O(n P^2)\)的dp。
考虑\(P\)为质数的情况。我们发现,对于所有\(a \neq 1\),\(\{a, 2a, \cdots, (P-1)a\}\)都是互不相等的,即它在模\(P\)意义下就是\(\{1, 2, \cdots , P-1\}\)。那么,在dp中\(1\)到\(P-1\)的所有数的转移都是相同的,那它们的答案也应当是相等的。
尝试把这个结论拓展到\(P\)为正整数的情况下。我们设模\(P\)意义下的每个数 $v = v' \times d $ ,其中 \(d=gcd(v,P)\) 。同样地,\(\{ v', 2v', \cdots , (P-1)v' \}\)互不相等,于是 \(v\) 乘以\(1\)到\(P-1\)的所有数就是\(\{d, 2d, \cdots , (P-1)d \}\)。于是,我们发现\(gcd(x,P)\)相同的\(x\)在dp中有相同的转移,那就可以把它们的状态合并在一起。这样这个dp就优化到了\(O(n \sigma (n)^2)\)的了,已经可以通过本题。
但我们还可以套路地对\(P\)做质因数分解,得到\(P = p_1^{a_1} p_2^{a_2} \cdots p_n^{a_n}\),然后以每个\(p_i^{a_i}\)为模数,分别求一次答案。考虑所有模\(P\)意义下的数和模\(p_i^{a_i}\)得到的序列是一一对应的,所以我们可知答案就是以每个\(p_i^{a_i}\)为模数的答案的积。那么,就能\(O(n \log^2 P + q \log P)\)地解决本题。(这里的\(\log P\)分析并不准确)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef double db;
#define fir first
#define sec second
class ModEquation {
public:
vector <int> count( int n, int K, vector <int> query ) ;
};
const int MAX = 100000, MP = 30, N = 60, MOD = (int)(1e9 + 7);
int isp[MAX + 10], pri[MAX], pcnt, fac[MP], fcnt, num[MP];
int power(int a,int b) {
int ret = 1;
while (b) {
if (b & 1) ret = 1ll * ret * a % MOD;
a = 1ll * a * a % MOD;
b >>= 1;
}
return ret;
}
void prework() {
for (int i = 2 ; i <= MAX ; ++ i) {
if (!isp[i]) pri[++pcnt] = i;
for (int j = 1 ; pri[j] * i <= MAX ; ++ j) {
isp[pri[j] * i] = 1;
if (i % pri[j] == 0) break;
}
}
}
int dp[MP][N][MP];
void init() {
pcnt = fcnt = 0;
memset(isp,0,sizeof isp);
memset(dp,0,sizeof dp);
}
vector <int> ModEquation::count(int n, int K, vector <int> query) {
init();
prework();
for (int i = 1 ; i <= pcnt ; ++ i) {
if (K % pri[i]) continue;
fac[++fcnt] = pri[i];
num[fcnt] = 0;
while (K % pri[i] == 0)
++ num[fcnt], K /= pri[i];
}
if (K != 1) {
++ fcnt;
fac[fcnt] = K;
num[fcnt] = 1;
}
for (int i = 1 ; i <= fcnt ; ++ i) {
dp[i][0][0] = 1;
for (int j = 0 ; j < n ; ++ j) {
for (int a = 0 ; a <= num[i] ; ++ a)
for (int b = num[i], t = 1 ; b >= 0 ; -- b, t *= fac[i]) {
(dp[i][j+1][min(num[i], a + b)] += 1ll * dp[i][j][a] * (t - t / fac[i]) % MOD) %= MOD;
}
}
for (int a = num[i], t = 1 ; a >= 0 ; -- a, t *= fac[i]) {
dp[i][n][a] = 1ll * dp[i][n][a] * power(t - t / fac[i], MOD - 2) % MOD;
}
}
vector<int> ans = vector<int>();
for (int id = 0 ; id < (int)query.size() ; ++ id) {
int v = query[id], ret = 1;
for (int i = 1 ; i <= fcnt ; ++ i) {
int tmp = v, rec = 0;
for (int j = 1 ; j <= num[i] ; ++ j)
if (tmp % fac[i] == 0) tmp /= fac[i], ++ rec;
ret = 1ll * ret * dp[i][n][rec] % MOD;
}
ans.push_back(ret);
}
return ans;
}
#undef fir
#undef sec
小结:数论题有一些基本结论和套路还是非常重要的。
【做题】SRM704 Div1 Median - ModEquation——数论的更多相关文章
- [日记&做题记录]-Noip2016提高组复赛 倒数十天
写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...
- noip做题记录+挑战一句话题解?
因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...
- NOIP2016考前做题(口胡)记录
NOIP以前可能会持续更新 写在前面 NOIP好像马上就要到了,感觉在校内训练里面经常被虐有一种要滚粗的感觉(雾.不管是普及组还是提高组,我都参加了好几年了,结果一个省一都没有,今年如果还没有的话感觉 ...
- UOJ 做题记录
UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...
- C语言程序设计做题笔记之C语言基础知识(下)
C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...
- C语言程序设计做题笔记之C语言基础知识(上)
C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...
- 屏蔽Codeforces做题时的Problem tags提示
当在Codeforces上做题的时,有时会无意撇到右侧的Problem tags边栏,但是原本并不希望能够看到它. 能否把它屏蔽了呢?答案是显然的,我们只需要加一段很短的CSS即可. span.tag ...
- ACM 做题过程中的一些小技巧。
ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...
- CodeM美团点评编程大赛复赛 做题感悟&题解
[T1] [简要题意] 长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...
随机推荐
- complex类
#include<iostream> #include<cmath> using namespace std; class complex{ public: complex() ...
- SecureCRT连接linux步骤
SecureCRT连接linux步骤 做个笔记,以免隔段时间后忘了 LINUX系统一般都是用来作服务器使用,而且都是通过命令行来操作,为了操作方便我们都会使用第三方软件来远程操作.CRT就是比较常用 ...
- 2PC/3PC/Paxos
在分布式系统中,一个事务可能涉及到集群中的多个节点.单个节点很容易知道自己执行的事务成功还是失败,但因为网络不可靠难以了解其它节点的执行状态(可能事务执行成功但网络访问超时). 若部分节点事务执行失败 ...
- win10系统电脑无法识别u盘的解决办法
一些win10系统用户说插入usb设备的时候出现无法识别usb设备的问题,就此问题,接下来是对应的解决方法. win10系统电脑无法识别U盘的应对方法: 右键“计算机”,从弹出的菜单中选择“属性”项: ...
- volatile有什么用?能否用一句话描述volatile的应用场景
volatile保证内存可见性和禁止指令重排.volatile用于多线程环境下的单次操作(单次读或者单次写).volatile关键字不能提供原子性. volatile关键字为实例域的同步访问提 ...
- ES6语法 Promise Iterator
类和对象 基本定义: class Parent{ constructor(name='lmx'){ //name= 默认值 this.name=name } } let v_parent = new ...
- [elk]验证mapping字段数和数据字段数关系
验证一个mapping下字段缺少或者超过 结论: 没有什么不可以. 1.如果数据字段不在mapping里,则动态会更新mapping. 2.数据字段数也可以小于mapping里字段数 创建一个mapp ...
- 创建存储过程 in,out,inout
in: 输入参数,存储过程如果修改了参数值,那么不能被返回. out:输出参数,存储过程中修改了参数值,可以被返回.inout:输入参数,存储过程如果修改了参数值,可以被返回 注意参数格式: in ...
- VS2017 异常 Editor or Editor Extension
KE遇到的第一个问题 VS 2017 打开文件的时候, 遇到异常 检查 activity_log发现是 Editor or Editor Extension, 解决办法: 安装插件, Clear ME ...
- Java文件类型工具类
package *; import java.util.HashMap; import java.util.Map; /** * <p> * <b>FileTypeEnum2& ...