题目

Source

http://acm.hdu.edu.cn/showproblem.php?pid=5322

Description

Hope is a good thing, which can help you conquer obstacles in your life, just keep fighting, and solve the problem below.

In mathematics, the notion of permutation relates to the act of arranging all the members of a set into some sequence or order, or if the set is already ordered, rearranging (reordering) its elements, a process called permuting. These differ from combinations, which are selections of some members of a set where order is disregarded. For example, written as tuples, there are six permutations of the set {1,2,3}, namely: (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), and (3,2,1). These are all the possible orderings of this three element set. As another example, an anagram of a word, all of whose letters are different, is a permutation of its letters. In this example, the letters are already ordered in the original word and the anagram is a reordering of the letters.
There is a permutation A1,A2,...An, now we define its value as below:
For each Ai, if there exists a minimum j satisfies j>i and Aj>Ai , then connect an edge between Ai and Aj , so after we connect all the edges, there is a graph G, calculate the product of the number of nodes in each component as an integer P. The permutation value is P * P.Now, Mr. Zstu wants to know the sum of all the permutation value of n. In case the answer is very big, please output the answer mod 998244353.
Just in case some of you can’t understand, all the permutations of 3 are
1 2 3
1 3 2
2 3 1
2 1 3
3 1 2
3 2 1

Input

There are multiple test cases.
There are no more than 10000 test cases.
Each test case is an integer n(1≤n≤100000).

Output

For each test case, output the answer as described above.

Sample Input

1
2

Sample Output

1
5

分析

题目大概说,对于1到n这n个数的任何一个排列A可以这样计算其价值:对所有下标i找到最小的j满足j>i且A[j]>A[i],然后i和j之间连边,最后所有连通块个数之积的平方就是该排列的价值。问所有排列的价值和是多少。

  • 首先要得出这么一个结论:从下标1...x,如果下标x的数是最大的话,那么1...x-1就与x一起组成一个连通块了。
  • 然后,$dp[i]表示i个互不相同的数的所有排列的价值和$
  • 通过枚举最大数的位置j来转移:$dp[i]\ =\ \sum A_{i-1}^{j-1}j^2dp[i-j]$
  • 可以整理成卷积形式:$dp[i]\ =\ (i-1)! \times \sum (j^2\times ((i-j)!)^{-1}dp[i-j])$
  • 然后于是就能用FFT计算了,特别的是结果模998244353,直接用NTT即可;还有要利用CDQ分治加速,累加左半边已经求得的dp值对右半边的影响。时间复杂度$O(nlog^2n)$。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 262144 const int P=998244353; // 119 * 2 ^ 23 + 1
const int G=3; long long mul(long long x,long long y){
return (x*y-(long long)(x/(long double)P*y+1e-3)*P+P)%P;
}
long long qpow(long long x,long long k,long long p){
long long ret=1;
while(k){
if(k&1) ret=mul(ret,x);
k>>=1;
x=mul(x,x);
}
return ret;
} long long wn[25];
void getwn(){
for(int i=1; i<=21; ++i){
int t=1<<i;
wn[i]=qpow(G,(P-1)/t,P);
}
} int len;
void NTT(long long y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
int id=0;
for(int h=2; h<=len; h<<=1) {
++id;
for(int i=0; i<len; i+=h){
long long w=1;
for(int j=i; j<i+(h>>1); ++j){
long long u=y[j],t=mul(y[j+h/2],w);
y[j]=u+t;
if(y[j]>=P) y[j]-=P;
y[j+h/2]=u-t+P;
if(y[j+h/2]>=P) y[j+h/2]-=P;
w=mul(w,wn[id]);
}
}
}
if(op==-1){
for(int i=1; i<len/2; ++i) swap(y[i],y[len-i]);
long long inv=qpow(len,P-2,P);
for(int i=0; i<len; ++i) y[i]=mul(y[i],inv);
}
}
void Convolution(long long A[],long long B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i]=B[i]=0;
} NTT(A,1); NTT(B,1);
for(int i=0; i<len; ++i){
A[i]=mul(A[i],B[i]);
}
NTT(A,-1);
} long long fact[MAXN]={1},fact_ine[MAXN]={1}; long long A[MAXN],B[MAXN];
long long d[MAXN]={1}; /*
d[i] = fact[i-1] * Σj*j * fact_ine[i-j]*d[i-j]
*/
void cdq(int l,int r){
if(l==r) return;
int mid=l+r>>1;
cdq(l,mid);
for(int i=l; i<=mid; ++i) A[i-l]=mul(fact_ine[i],d[i]);
for(int i=1; i<=r-l; ++i) B[i]=mul(i,i);
for(int i=mid-l+1; i<=r-l; ++i) A[i]=0;
Convolution(A,B,r-l+1);
for(int i=mid+1; i<=r; ++i){
d[i]+=mul(A[i-l],fact[i-1]);
d[i]%=P;
}
cdq(mid+1,r);
} int main(){
for(int i=1; i<=100000; ++i){
fact[i]=mul(fact[i-1],i);
fact_ine[i]=qpow(fact[i],P-2,P);
}
getwn();
cdq(0,100000);
int n;
while(~scanf("%d",&n)){
printf("%I64d\n",d[n]);
}
return 0;
}

HDU5322 Hope(DP + CDQ分治 + NTT)的更多相关文章

  1. Tsinsen A1493 城市规划(DP + CDQ分治 + NTT)

    题目 Source http://www.tsinsen.com/A1493 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在 ...

  2. hdu5322 Hope(dp+FFT+分治)

    hdu5322 Hope(dp+FFT+分治) hdu 题目大意:n个数的排列,每个数向后面第一个大于它的点连边,排列的权值为每个联通块大小的平方,求所有排列的权值和. 思路: 考虑直接设dp[i]表 ...

  3. 【BZOJ-3456】城市规划 CDQ分治 + NTT

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=3456 Solution 这个问题可以考虑dp,利用补集思想 N个点的简单图总数量为$2^{ ...

  4. bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...

  5. 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治

    题目描述  给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...

  6. 斜率dp cdq 分治

    f[i] = min { f[j] + sqr(a[i] - a[j]) } f[i]= min { -2 * a[i] * a[j] + a[j] * a[j] + f[j] } + a[i] * ...

  7. BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )

    考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N)  F, T均为后缀和. 与j有关 ...

  8. bzoj1492--斜率优化DP+cdq分治

    显然在某一天要么花完所有钱,要么不花钱. 所以首先想到O(n^2)DP: f[i]=max{f[i-1],(f[j]*r[j]*a[i]+f[j]*b[i])/(a[j]*r[j]+b[j])},j& ...

  9. bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2726 [题意] 将n个任务划分成若干个块,每一组Mi任务花费代价(T+sigma{ t ...

随机推荐

  1. Oracle表格建立

    Oracle学习第一天:学习了如何在网页上建立表空间,以及在关联性表格上建立表格,填充表格,学习了如何建立自己的表空间.效果如下:

  2. 安卓3D游戏-神奇宝贝防御战

    我和同学用unity引擎做的,作为软件工程的大作业. 是一个花费金钱抓怪.控制怪物站位.击杀进攻的敌人获得金钱的类似塔防的安卓游戏. 下载地址:http://pan.baidu.com/s/1gdpH ...

  3. NEERC2014 Eastern subregional

    \ 先把furthur的超碉线段树粘过来 //#pragma comment(linker, "/STACK:102400000,102400000") #include<c ...

  4. JavaScript模板引擎原理,几行代码的事儿

    一.前言 什么是模板引擎,说的简单点,就是一个字符串中有几个变量待定.比如: var tpl = 'Hei, my name is <%name%>, and I\'m <%age% ...

  5. ubuntu12.04server下red5-1.0.0RC1的部署

    一.搭建环境 Linux版本:ubuntu12.04sever  64位 Java  版本:Java 1.7(jdk+jre) Red5 版本:red5-1.0.0-RC1 二.安装JDK 下载jdk ...

  6. TopHat

    What is TopHat? TopHat is a program that aligns RNA-Seq reads to a genome in order to identify exon- ...

  7. 大组合数:Lucas定理

    最近碰到一题,问你求mod (p1*p2*p3*……*pl) ,其中n和m数据范围是1~1e18 , l ≤10 , pi ≤ 1e5为不同的质数,并保证M=p1*p2*p3*……*pl ≤ 1e18 ...

  8. PHP mkdir 0777权限问题

    在linux系统中,即使我们使用root帐号去手工执行php命令: mkdir('test', 0777); 结果文件的权限依然为: drwxr-xr-x 2 root root 4096 Jun 1 ...

  9. Effective C++ 34 区分接口继承和实现继承

    public继承从根本上讲,有两部分:接口继承和实现继承.两者之前的区别很像函数声明与函数定义. 具体设计中,会呈现三种形式:derived class只继承成员函数的接口(纯虚函数):derived ...

  10. iOS开发——UI进阶篇(十九)UISearchBar控件简介

    最近用到搜索功能.总结一下 搜索,无疑可以使用UISearchBar控件! 那就先了解一下UISearchBar控件吧! UISearchBar控件就是要为你完成搜索功能的一个专用控件.它集成了很多你 ...