NTT【51nod】1514 美妙的序列

题意:1~n 的全排列中,有多少个排列满足任意从中间切成两段后,左边段的最大值大于右边段的最小值?

例如:n为3时有3种

2 3 1

3 1 2

3 2 1

解释:比如 2 3 1

(2) (3 1) 1比2小

(2 3) (1) 1比2小

都满足上面的条件。

3 2 1

(3)(2 1) 1比3小

(32)(1)  1比3小

都满足上面的条件。

而2 1 3不满足,因为(2 1)(3),3比左边所有的数都大。

====================================分割线====================================

首先序列为美妙的等价于不存在(1<=i<n)使得 前i个数为1~i的排列

令f[n]为长度为n的答案

则:

f[0]=0

f[i]=i!-sigma(f[j]*(i-j)!)  0<=j<i

我们将其变形

Sigma(f[j]*(i-j)!) = i!   i > 0, j=0~i

Sigma(f[j]*(i-j)!) = 0   i = 0, j=0~i

令G(x)=sigma(i!*x^i),F(x)=sigma(f[i]*x^i)

F(x)*G(x)=G(x)-1  (减一为i = 0的情况)

F(x)=(G(x)-1)/G(x)=1-1/G(x)

多项式求逆即可

 1 #include<cstdio>
 2 #include<iostream>
 3 typedef long long ll;
 4 using namespace std;
 5 const int N = 262144, K = 17;
 6 int n, m, i, k;
 7 int a[N+10], b[N+10], tmp[N+10], tmp2[N+10];
 8 int P = 998244353, G = 3, g[K+1], ng[K+10], inv[N+10], inv2;
 9 int pow(int a,int b){int t=1;for(;b;b>>=1,a=(ll)a*a%P)if(b&1)t=(ll)t*a%P;return t;}
10 void NTT(int*a,int n,int t){
11     for(int i=1,j=0;i<n-1;i++){
12         for(int s=n;j^=s>>=1,~j&s;);
13         if(i<j)swap(a[i], a[j]);
14     }
15     for(int d=0;(1<<d)<n;d++){
16         int m=1<<d,m2=m<<1,_w=t==1?g[d]:ng[d];
17         for(int i=0;i<n;i+=m2)for(int w=1,j=0;j<m;j++){
18             int&A=a[i+j+m],&B=a[i+j],t=(ll)w*A%P;
19             A=B-t;if(A<0)A+=P;
20             B=B+t;if(B>=P)B-=P;
21             w=(ll)w*_w%P;
22         }
23     }
24     if(t==-1)for(int i=0,j=inv[n];i<n;i++)a[i]=(ll)a[i]*j%P;
25 }
26 //给定a,求a的逆元b
27 void getinv(int*a,int*b,int n){
28     if(n==1){b[0]=pow(a[0],P-2);return;}
29     getinv(a,b,n>>1);
30     int k=n<<1,i;
31     for(i=0;i<n;i++)tmp[i]=a[i];
32     for(i=n;i<k;i++)tmp[i]=b[i]=0;
33     NTT(tmp,k,1),NTT(b,k,1);
34     for(i=0;i<k;i++){
35     b[i]=(ll)b[i]*(2-(ll)tmp[i]*b[i]%P)%P;
36     if(b[i]<0)b[i]+=P;
37     }
38     NTT(b,k,-1);
39     for(i=n;i<k;i++)b[i]=0;
40 }
41 int main(){
42     for(g[K]=pow(G,(P-1)/N),ng[K]=pow(g[K],P-2),i=K-1;~i;i--)
43         g[i]=(ll)g[i+1]*g[i+1]%P,ng[i]=(ll)ng[i+1]*ng[i+1]%P;
44     for(inv[1]=1,i=2;i<=N;i++)inv[i]=(ll)(P-inv[P%i])*(P/i)%P;inv2=inv[2];
45     int len = 1;
46     while(len <= 100000) len <<= 1;
47     a[0] = 1;
48     for(int i = 1; i < len; i++)
49         a[i] = (ll)i*a[i-1]%P;
50     getinv(a, b, len);
51     for(int i = 0; i < len; i++)
52         b[i] = (-b[i]+P)%P;
53     b[0]++;
54     int t, n; scanf("%d", &t);
55     while(t--){
56         scanf("%d", &n);
57         printf("%d\n", b[n]);
58     }
59     return 0;
60 }

时间: 2024-10-18 02:46:12

NTT【51nod】1514 美妙的序列的相关文章

【51nod】1251 Fox序列的数量

题解 容斥题 我们枚举出现次数最多的数出现了K次 然后我们需要计算的序列是所有数字出现个数都不超过K - 1次 我们枚举不合法的数字的数目j,说明这个排列里除了我们固定出现K次的数至少有j个数是不合法的,先让这j个数每个数出现k次,然后再随意排列 j最大是N / K 那么复杂度就是调和级数了 代码 #include <bits/stdc++.h> //#define ivorysi #define enter putchar('\n') #define space putchar(' ') #

【51nod 1251】 Fox序列的数量(以及带限制插板法讲解)

为什么网上没有篇详细的题解[雾 可能各位聚聚觉得这道题太简单了吧 /kk 题意 首先题目是求满足条件的序列个数,条件为:出现次数最多的数仅有一个 分析 感谢 刚睡醒的 JZ姐姐在咱写题解忽然陷入自闭的时候为咱知道迷津 QwQ 那么套路来说第一想到的其实就是容斥辣 然后懒得想去网上黈力[雾 在然后,发现网上要么没推导公式(虽说是直接列不用化简的)要么就是推导公式是错的... 于是坐下来冷静分析:首先,我们考虑最高的出现次数为 x 的情况下,有多少个序列是满足条件的 容斥一发发现式子长这个样子(用到

【51NOD 1478】括号序列的最长合法子段

很恶心啊,一道水题改了半天,主要是各种细节没有注意到,包括左括号剩余时有可能会出错的情况,需要从后往前扫 贡献一组测试数据: ((()))())(())(( 答案:8 1 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1E6 + 3; char s[N]; int main() { scanf("%s", s); in

【51Nod 1341】混合序列 矩阵快速幂

题意 给定两个数列\(a_n=pa_{n-1}+r,a_0=0\) , \(b_n=qb_{n-1},b_0=3\) , 求\(\sum_{i=0}^{n}a_i\times b_{n-i} \mod {1e9+7}\) 如果\(n\)的范围是\(1e7\),可以用FFT加速卷积 这题范围过大,所以只能用别的方法 令\(f_n=\sum_{i=0}^{n}a_i\times b_{n-i}\) , 那么\(f_{n+1}=\sum_{i=0}^{n+1}a_i\times b_{n+1-i}=\

51Nod 快速傅里叶变换题集选刷

打开51Nod全部问题页面,在右边题目分类中找到快速傅里叶变换,然后按分值排序,就是本文的题目顺序. 1.大数乘法问题 这个……板子就算了吧. 2.美妙的序列问题 长度为n的排列,且满足从中间任意位置划分为两个非空数列后,左边的最大值>右边的最小值.问这样的排列有多少个%998244353. 多组询问,n,T<=100000. 题解:经过分析可知,不合法的排列一定存在这样一种划分: 我们考虑答案=f[i]=i!-不合法排列个数. 形如 2 1 3 4 6 5 这种排列,会有三种划分方式不合法(

11.1 上午考试

完美的序列(sequence)Time Limit:1000ms Memory Limit:64MB题目描述LYK 认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同.然而并不是所有的序列都满足这样的条件.于是 LYK 想将序列上的每一个元素都增加一些数字(当然也可以选择不增加),使得整个序列变成美妙的序列.具体地, LYK 可以花费 1 点代价将第 i 个位置上的数增加 1,现在 LYK 想花费最小的代价使得将这个序列变成完美的序列.输入格式(sequence.in)第一行一个

11.1 morning

完美的序列(sequence)Time Limit:1000ms Memory Limit:64MB题目描述LYK 认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同.然而并不是所有的序列都满足这样的条件.于是 LYK 想将序列上的每一个元素都增加一些数字(当然也可以选择不增加),使得整个序列变成美妙的序列.具体地, LYK 可以花费 1 点代价将第 i 个位置上的数增加 1,现在 LYK 想花费最小的代价使得将这个序列变成完美的序列.输入格式(sequence.in)第一行一个

BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂

3992: [SDOI2015]序列统计 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1155  Solved: 532[Submit][Status][Discuss] Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中

【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个.小C认为,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi.另外,小C认为这个问题的答案可能