LOJ #2183「SDOI2015」序列统计
有好多好玩的知识点
题意:在集合中选$ n$个元素(可重复选)使得乘积模$ m$为$ x$,求方案数对$ 1004535809$取模
$ n<=10^9,m<=8000且是质数,集合大小不超过m$
$ Solution:$
我们先考虑改乘积为加和之后怎么做
直接对于集合中的数构建生成函数
所要求的就是这个生成函数的$ n$次幂的所有模$ m$为$ c$的项的系数的和
用快速幂优化这个生成函数的$ n$次幂
每次乘法之后立刻把$ [m,2m)$的系数加回$[0,m)$
这样可以保证每时每刻生成函数的长度不超过$ m$
就可以直接$ NTT$优化这个过程了
时间复杂度为$ O(m log m log n)$
然后考虑乘积的情况
我们知道$ x^ax^b=x^{a+b}$
尝试把每个数改成某个底数的若干次方
由于$ m$是质数一定存在原根
原根有性质是它的$[0,phi(m))$在模$ m$意义下互不相同
这样就可以直接把每个集合中的数改成$ m$的原根的若干次方就好了
然后就是加和情况的做法
复杂度不变
注意可能要特判原集合中存在$ 0$的情况
$ my \ code$
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define p 1004535809
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x = ; char zf = ; char ch = getchar();
while (ch != '-' && !isdigit(ch)) ch = getchar();
if (ch == '-') zf = -, ch = getchar();
while (isdigit(ch)) x = x * + ch - '', ch = getchar(); return x * zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int i,j,k,m,n,x,y,z,cnt,c,yg;
int a[],val[];
namespace NTT{
int ksm(int x,int y){
int ans=;
for(rt i=y;i;i>>=,x=1ll*x*x%p)if(i&)ans=1ll*x*ans%p;
return ans;
}
vector<int>R;
void NTT(int n,vector<int>&A,int fla){
A.resize(n);
for(rt i=;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]);
for(rt i=;i<n;i<<=){
int w=ksm(,(p-)//i);
for(rt j=;j<n;j+=i<<){
int K=;
for(rt k=;k<i;k++,K=1ll*K*w%p){
const int x=A[j+k],y=1ll*K*A[i+j+k]%p;
A[j+k]=(x+y)%p,A[i+j+k]=(x-y)%p;
}
}
}
if(fla==-){
reverse(A.begin()+,A.end());
int invn=ksm(n,p-);
for(rt i=;i<n;i++)A[i]=1ll*A[i]*invn%p;
}
}
void mul(int del,int n,vector<int>&A){
NTT(n,A,);
for(rt i=;i<n;i++)A[i]=1ll*A[i]*A[i]%p;
NTT(n,A,-);
for(rt i=del;i<n;i++)(A[i%del]+=A[i])%=p,A[i]=;
}
void calc(int n,vector<int>&A,int y,int pl){
int lim=;
while(lim<=n*+)lim<<=;
R.resize(lim);A.resize(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|((i&)*(lim>>));
vector<int>ans;ans.resize(lim);
ans[]=;
for(rt i=y;i;i>>=,mul(n,lim,A))if(i&){
NTT(lim,ans,);NTT(lim,A,);
for(rt j=;j<lim;j++)ans[j]=1ll*ans[j]*A[j]%p;
NTT(lim,ans,-);NTT(lim,A,-);
for(rt j=n;j<lim;j++)(ans[j%n]+=ans[j])%=p,(A[j%n]+=A[j])%=p,ans[j]=,A[j]=;
}
writeln((ans[pl]+p)%p);
}
};
vector<int>A,B;
using namespace NTT;
int main(){
n=read();m=read();c=read();k=read();
A.resize(m+);
for(rt i=;i<=m;i++){
for(rt j=,k=i;j<m-;j++,k=1ll*k*i%m)if(k==)goto GG;
yg=i;break;
GG:;
}
for(rt i=,j=;i<m-;i++,j=1ll*yg*j%m)val[j]=i;
for(rt i=;i<=k;i++){
x=read();if(x)A[val[x]]++;
}
calc(m-,A,n,val[c]);
return ;
}
LOJ #2183「SDOI2015」序列统计的更多相关文章
- 【LOJ】#2183. 「SDOI2015」序列统计
题解 这个乘积比较麻烦,转换成原根的指数乘法就相当于指数加和了,可以NTT优化 注意判掉0 代码 #include <bits/stdc++.h> #define fi first #de ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
- loj #2051. 「HNOI2016」序列
#2051. 「HNOI2016」序列 题目描述 给定长度为 n nn 的序列:a1,a2,⋯,an a_1, a_2, \cdots , a_na1,a2,⋯,an,记为 a[1: ...
- LOJ 3158: 「NOI2019」序列
题目传送门:LOJ #3158. 题意简述: 给定两个长度为 \(n\) 的正整数序列 \(a,b\),要求在每个序列中都选中 \(K\) 个下标,并且要保证同时在两个序列中都被选中的下标至少有 \( ...
- LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分
题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...
- loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)
题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
- Loj 3058. 「HNOI2019」白兔之舞
Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...
随机推荐
- 关于MySQL锁的详解
有2种 1.表锁 2.行锁 支持 .innodb支持行锁,表级锁 .myisam只支持表级锁 innodb实现了下面2种标准的行级锁 .共享锁 S LOCK 允许事务读一行数据 .排他锁 X LOCK ...
- c++ sort
老是搞混 return bool eg. bool cmp(node a,node b) { if (a.score==b.score) ; else return a.score>b.scor ...
- 千人基因组(1000 Genomes)提取群体(population)或者样本(sample ID)信息
进入链接:http://www.internationalgenome.org/data-portal/sample 点击“filter by population”,在弹出的选择框里,选择想要下载的 ...
- tail 命令只查看日志中的关键字所在行信息
tail -f info_log-2019-04-20.log |grep 要查询的关键字
- Transactional 事务
1.事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚 其实像第一种try catch这种把整个包裹起来,这种业务方法也就等于脱离了spring事务的管理,因为没有任何异常会从业务方法中 ...
- WPF开发的界面调用C++生成的dll文件
以引用d1.dll为例. [生成d1.dll] 文件——新建——项目——Visual C++——Win32项目,选择DLL,点击Finish.在d1.cpp中添加代码 #include "s ...
- 1、CC2530单片机介绍
单片机是一种集成电路芯片,包含中央处理器CPU.随机存储器RAM.只读存储器ROM.输入输出I/O接口.中断控制系统.定时/计数器和通信等多种功能部件. 本教程使用的单片机德州仪器生产的CC2530, ...
- JS数据交换的三种方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js 各种事件 如:点击事件、失去焦点、键盘事件等
事件驱动: 我们点击按钮 按钮去掉用相应的方法. demo: <input type="button" v ...
- sklearn—特征工程
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...