码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5530

时间:2017-12-17 12:11:49      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:for   close   hid   print   type   space   一个   pow   连通块   

分治ntt

考虑从添加i,放在j位置,那么1->j是一个连通块,j+1->i和1->j不连通,那么我们可以列出式子dp[i]=∑j=1->i dp[i-j]*A(i-1,j-1)*j^2

dp[i]表示i个数的答案

然后化简一下就可以分治ntt了

技术分享图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 5, P = 998244353;
int n, k;
ll a[N], b[N], fac[N], inv[N], facinv[N], dp[N];
ll power(ll x, ll t)
{
    ll ret = 1;
    for(; t; t >>= 1, x = x * x % P) if(t & 1) ret = ret * x % P;
    return ret;
}
void ntt(ll *a, int f)
{
    for(int i = 0; i < n; ++i)
    {
        int t = 0;
        for(int j = 0; j < k; ++j) if(i >> j & 1) t |= 1 << (k - j - 1);
        if(i < t) swap(a[i], a[t]);
    }
    for(int l = 2; l <= n; l <<= 1)
    {
        ll w = power(3, f == 1 ? (P - 1) / l : P - 1 - (P - 1) / l);
        int m = l >> 1;
        for(int i = 0; i < n; i += l)
        {
            ll t = 1;
            for(int k = 0; k < m; ++k, t = t * w % P)
            {
                ll x = a[i + k], y = t * a[i + m + k];
                a[i + k] = (x + y) % P;
                a[i + m + k] = ((x - y) % P + P) % P;
            }    
        }
    }
    if(f == -1)
    {
        ll inv = power(n, P - 2);
        for(int i = 0; i < n; ++i) a[i] = a[i] * inv % P;
    }
}
void cdq(int l, int r)
{
    if(l == r) return;
    int mid = (l + r) >> 1;
    cdq(l, mid);
    n = 1;
    k = 0;
    while(n <= r - l + 1) n <<= 1, ++k;
    for(int i = 0; i < n; ++i) a[i] = b[i] = 0;
    for(int i = l; i <= mid; ++i) a[i - l] = dp[i] * facinv[i] % P;
    for(int i = 1; i <= r - l; ++i) b[i] = (ll)i * i % P;
    ntt(a, 1);
    ntt(b, 1);
    for(int i = 0; i < n; ++i) a[i] = a[i] * b[i] % P;
    ntt(a, -1);
    for(int i = mid + 1; i <= r; ++i) dp[i] = (dp[i] + a[i - l] * fac[i - 1] % P) % P;
    cdq(mid + 1, r); 
}
int main()
{
    inv[0] = inv[1] = facinv[0] = fac[0] = 1;
    for(int i = 1; i < N; ++i)
    {
        if(i != 1) inv[i] = (P - P / i) * inv[P % i] % P;
        facinv[i] = facinv[i - 1] * inv[i] % P;
        fac[i] = fac[i - 1] * i % P;
    }
    dp[0] = 1;
    cdq(0, 100000); 
    while(scanf("%d", &n) != EOF)
    {
        
        printf("%lld\n", dp[n]);
    }
    return 0;
}
View Code

 

hdu5530

标签:for   close   hid   print   type   space   一个   pow   连通块   

原文地址:http://www.cnblogs.com/19992147orz/p/8051484.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!