题目大意:给你一个集合$n,m,x,S(S_i\in(0,m],m\leqslant 8000,m\in \rm{prime},n\leqslant10^9)$,求一个长度为$n$的序列$Q$,满足$Q_i\in S$,且$\prod\limits _{i=1}^nQ_i=x$,求序列的个数

题解:乘比较麻烦,可以把每个数求$\ln$,可以求出$m$的原根,求原根可以暴力$O(m^2)$求,然后每个数求$\ln$,求出生成函数$F(x)$,算出$F^n(x)$。发现$n$较大,多项式快速幂即可。

卡点:

C++ Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 16384 | 3
#define maxm 8010
const int mod = 1004535809, G = 3;
int n, m, x, S, g;
int vis[maxm];
int get(int m) {
bool find = false;
for (int i = 2; i < m; i++) {
memset(vis, -1, sizeof vis);
int t = 1;
vis[1] = 0;
for (int j = 1; j < m - 1; j++) {
t = t * i % m;
if (~vis[t]) break;
else vis[t] = j;
if (j == m - 2) find = true;
}
if (find) return i;
}
return 20040826;
}
int lim, ilim, s, rev[maxn];
int base[maxn], ans[maxn], Wn[maxn + 1];
inline int pw(int base, int p) {
int res = 1;
for (; p; p >>= 1, base = 1ll * base * base % mod) if (p & 1) res = 1ll * res * base % mod;
return res;
}
inline int Inv(int x) {return pw(x, mod - 2);}
inline void init(int n) {
lim = 1, s = -1; while (lim < n) lim <<= 1, s++; ilim = Inv(lim);
for (int i = 0; i < lim; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
int t = pw(G, (mod - 1) / lim);
Wn[0] = 1; for (int i = 1; i <= lim; i++) Wn[i] = 1ll * Wn[i - 1] * t % mod;
}
inline void up(int &a, int b) {if ((a += b) >= mod) a -= mod;}
inline void NTT(int *A, int op) {
for (int i = 0; i < lim; i++) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
for (int mid = 1; mid < lim; mid <<= 1) {
int t = lim / mid >> 1;
for (int i = 0; i < lim; i += mid << 1) {
for (int j = 0; j < mid; j++) {
int W = op ? Wn[j * t] : Wn[lim - j * t];
int X = A[i + j], Y = 1ll * A[i + j + mid] * W % mod;
up(A[i + j], Y), up(A[i + j + mid] = X, mod - Y);
}
}
}
if (!op) for (int i = 0; i < lim; i++) A[i] = 1ll * A[i] * ilim % mod;
}
int C[maxn], D[maxn];
inline void MUL(int *A, int *B) {
for (int i = 0; i < lim; i++) C[i] = A[i], D[i] = B[i];
NTT(C, 1), NTT(D, 1);
for (int i = 0; i < lim; i++) C[i] = 1ll * C[i] * D[i] % mod;
NTT(C, 0);
for (int i = 0; i < lim; i++) A[i] = C[i];
for (int i = m - 1; i < lim; i++) (A[i % (m - 1)] += A[i]) %= mod, A[i] = 0;
}
int main() {
scanf("%d%d%d%d", &n, &m, &x, &S);
g = get(m);
for (int i = 0, tmp; i < S; i++) {
scanf("%d", &tmp);
if (tmp) base[vis[tmp]] = 1;
}
init(m << 1);
ans[0] = 1;
for (; n; n >>= 1, MUL(base, base)) if (n & 1) MUL(ans, base);
printf("%d\n", ans[vis[x]]);
return 0;
}

  

[洛谷P3321][SDOI2015]序列统计的更多相关文章

  1. 洛谷P3321 [SDOI2015]序列统计(NTT)

    传送门 题意:$a_i\in S$,求$\prod_{i=1}^na_i\equiv x\pmod{m}$的方案数 这题目太珂怕了……数学渣渣有点害怕……kelin大佬TQL 设$f[i][j]$表示 ...

  2. 洛咕 P3321 [SDOI2015]序列统计

    显然dp就是设\(f[i][j]\)表示dp了i轮,对m取膜是j的方案数 \(f[i][xy\mod m]=f[i-1][x]\times f[i-1][y]\) 这是\(O(nm^2)\)的 像我这 ...

  3. 洛谷3321 SDOI2015 序列统计

    懒得放传送[大雾 有趣的一道题 前几天刚好听到Creed_神犇讲到相乘转原根变成卷积的形式 看到这道题当然就会做了啊w 对于m很小 我们暴力找原根 如果你不会找原根的话 出门左转百度qwq 找到原根以 ...

  4. P3321 [SDOI2015]序列统计 FFT+快速幂+原根

    \(\color{#0066ff}{ 题目描述 }\) 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这 ...

  5. P3321 [SDOI2015]序列统计

    思路 首先有个挺显然的DP \[ dp[i][(j*k)\%m]+=dp[i-1][j]\times dp[i-1][k] \] 想办法优化这个DP 这个dp也可以写成这样 \[ dp[i][j]=\ ...

  6. Luogu P3321 [SDOI2015]序列统计

    一道不错的多项式好题.还涉及了一些数论内容. 首先我们看到题目是求乘积模\(m\)的方案数,考虑到这种方案数我们一般都可以用生成函数来做. 但显然卷积的下标有加(FFT,NTT等)有位运算(FWT)但 ...

  7. 【LG3321】[SDOI2015]序列统计

    [LG3321][SDOI2015]序列统计 题面 洛谷 题解 前置芝士:原根 我们先看一下对于一个数\(p\),它的原根\(g\)有什么性质(好像就是定义): \(g^0\%p,g^1\%p,g^2 ...

  8. BZOJ 3992: [SDOI2015]序列统计 [快速数论变换 生成函数 离散对数]

    3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1017  Solved: 466[Submit][Statu ...

  9. [SDOI2015]序列统计

    [SDOI2015]序列统计 标签: NTT 快速幂 Description 给你一个模m意义下的数集,需要用这个数集生成一个数列,使得这个数列在的乘积为x. 问方案数模\(1004535809\). ...

随机推荐

  1. C#后台动态添加Grid表格

    前面页面: <ScrollViewer x:Name=" BorderBrush="#25A0DA" VerticalScrollBarVisibility=&qu ...

  2. vue面试常被问到的问题整理

    1.Vue的双向数据绑定原理是什么? 答 : vue是采用数据劫持,并且使用发布-订阅者的开发模式.原理是观察者observer通过Object.defineProperty()来劫持到各个属性的ge ...

  3. Java - 得到项目中properties属性文件中定义的属性值

    public static String getPropertiesValue(String fileName, String key) {   return ResourceBundle.getBu ...

  4. 【c学习-2】

    #include <stdio.h> #define MYVAR 18 int main(){ //float x=3.14; //x=3.14++; //printf("%c\ ...

  5. 第1章 HTML5 概述

    第 1 章  HTML5 概述 学习要点: 1.HTML5 的历史 2.HTML5 的功能 3.HTML5 的特点 4.课程学习问题 HTML5 是继 HTML4.01 和 XHTML1.0 之后的超 ...

  6. PTA 7-12(图) 社交网络图中结点的“重要性”计算 最短路

    7-12(图) 社交网络图中结点的“重要性”计算 (30 分) 在社交网络中,个人或单位(结点)之间通过某些关系(边)联系起来.他们受到这些关系的影响,这种影响可以理解为网络中相互连接的结点之间蔓延的 ...

  7. 一行代码将两个列表拼接出第三个列表(两个可迭代对象相加产生第三个可迭代对象)--map()方法

    map()方法 map(func, *iterables) --> map object lambda方法: lambda  参数 :返回值 a = map(',7]) print(list(a ...

  8. Android面试收集录8 HandlerThread详解

    1.前言 我们知道在Android系统中,我们执行完耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁. 想象一下如果我们在项目中经常要执行耗时操作,如果经常要开启线程,接着又销毁线程, ...

  9. PHP.22-Smart模版

    Smart模版 smarty是一个基于PHP开发的PHP模板引擎.它提供了逻辑与外在内容的分离,简单的讲,目的就是要使PHP程序员同美工分离,使用的程序员改变程序的逻辑内容不会影响到美工的页面设计,美 ...

  10. [bzoj2733]永无乡&&[bzoj3545]Peaks

    并不敢说完全会了线段树合并,只是至少知道原理写法了...还是太菜了,每天被大佬吊锤qwq 我看到的几道线段树合并都是权值线段树的合并.这个算法适用范围应该只是01线段树的. 这两道算入门题了吧... ...