hdu 5322 Hope

Hope

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 456 Accepted Submission(s): 251

Problem 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

Author
ZSTU

Source
2015 Multi-University Training Contest 3

Recommend
wange2014 | We have carefully selected several similar problems for you: 6032 6031 6030 6029 6028


【分析】

题意:

给定n,考虑一个1,2,…,n的排列A[1],A[2],…,A[n],对于每个i,选取最小的j(若存在)使得j>i且A[j]>A[i],则在i到j之间连一条边,记P为图中所有连通块的大小之积,定义P*P为这个排列的permutation value,求出所有1,2,…,n的排列的permutation value之和对998244353取模的值。

[题意 copy from quailty ]

n 的答案为dp[n]

考虑枚举数字 n 放在第几个位置

dp[n]=ni=1(i1)!C(n1,i1)i2dp[ni]

考虑展开C,得到:

dp[n]=(n1)!n1i=0(ni)2i!

这是个卷积…CDQ+NTT…
初始化 dp[0]=1


【代码】

//hdu 5322 Hope
#include<bits/stdc++.h>
#define M 100000
#define ll long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
const int mod=998244353;
const int mxn=400005;
int n,m,T,L;
int a[mxn],b[mxn],dp[mxn];
int fac[mxn],inv[mxn],R[mxn];
inline int read()
{
    int x=0;char ch=getchar();
    while(ch<'0' || ch>'9') ch=getchar();
    while(ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return x;
}
inline int power(int x,int k)
{
    int res=1;
    while(k)
    {
        if(k&1) res=(ll)res*x%mod;
        x=(ll)x*x%mod,k>>=1;
    }
    return res;
}
inline void NTT(int *a,int f)
{
    fo(i,0,n-1) if(i<R[i]) swap(a[i],a[R[i]]);
    for(int i=1;i<n;i<<=1)
    {
        int wn=power(3,(mod-1)/(i<<1));
        for(int j=0;j<n;j+=(i<<1))
        {
            int w=1;
            for(int k=0;k<i;k++,w=(ll)w*wn%mod)
            {
                int x=a[j+k],y=(ll)w*a[j+k+i]%mod;
                a[j+k]=(x+y)%mod;
                a[j+k+i]=(x-y+mod)%mod;
            }
        }
    }
    if(f==-1)
    {
        reverse(a+1,a+n);
        int rev=power(n,mod-2);
        fo(i,0,n-1) a[i]=(ll)a[i]*rev%mod;
    }
}
inline void CDQ(int l,int r)
{
    if(l==r)
    {
        if(l==0) return;
        dp[l]=(ll)dp[l]*fac[l-1]%mod;
        return;
    }
    int mid=l+r>>1;
    CDQ(l,mid);

    n=r-l,m=n+n;
    fo(i,0,4*n) a[i]=b[i]=0;
    fo(i,l,mid) a[i-l]=(ll)dp[i]*inv[i]%mod;
    fo(i,0,r-l) b[i]=(ll)i*i%mod;
    for(n=1,L=0;n<=m;n<<=1) L++;
    fo(i,0,n-1) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
    NTT(a,1),NTT(b,1);
    fo(i,0,n) a[i]=(ll)a[i]*b[i]%mod;
    NTT(a,-1);
    fo(i,mid+1,r) dp[i]=(dp[i]+a[i-l])%mod;

    CDQ(mid+1,r);
}
inline void init()
{
    fac[0]=inv[0]=inv[1]=1;
    fo(i,1,M) fac[i]=(ll)fac[i-1]*i%mod;
    fo(i,2,M) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
    fo(i,1,M) inv[i]=(ll)inv[i]*inv[i-1]%mod;
    dp[0]=1,CDQ(0,M);
}
int main()
{
    init();
    while(scanf("%d",&n)!=EOF)
      printf("%d\n",dp[n]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值