# 【bzoj5161】最长上升子序列 状压dp+打表

2

499122178

#include <cstdio>
#include <cstring>
#define mod 998244353
typedef long long ll;
int f[2][134217735] , cnt[134217735];
ll pow(ll x , int y)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
int main()
{
int n , i , j , k , d , t , pos;
ll ans = 0 , fac = 1;
scanf("%d" , &n) , n -- ;
f[0][0] = 1;
for(d = i = 1 ; i <= n ; i ++ , d ^= 1)
{
memset(f[d] , 0 , sizeof(int) * (1 << i));
for(j = 0 ; j < (1 << (i - 1)) ; j ++ )
{
f[d][j << 1] = (f[d][j << 1] + f[d ^ 1][j]) % mod , pos = -1;
for(k = i - 1 ; ~k ; k -- )
{
t = ((j >> k) << (k + 1)) | (1 << k) | (j & ((1 << k) - 1));
if(j & (1 << k)) pos = k;
if(~pos) t ^= (1 << (pos + 1));
f[d][t] = (f[d][t] + f[d ^ 1][j]) % mod;
}
}
}
for(i = 1 ; i < (1 << n) ; i ++ ) cnt[i] = cnt[i - (i & -i)] + 1;
for(i = 0 ; i < (1 << n) ; i ++ ) ans = (ans + 1ll * f[n & 1][i] * (cnt[i] + 1)) % mod;
for(i = 1 ; i <= n + 1 ; i ++ ) fac = fac * i % mod;
printf("%lld\n" , ans * pow(fac , mod - 2) % mod);
return 0;
}


AC程序：

#include <cstdio>
int a[]={1,499122178,2,915057326,540715694,946945688,422867403,451091574,317868537,200489273, 976705134,705376344,662845575,331522185,228644314,262819964,686801362,495111839,947040129,414835038,696340671,749077581,301075008,314644758,102117126,819818153,273498600,267588741},n;
int main()
{
scanf("%d",&n);
printf("%d",a[n-1]);
return 0;
}


posted @ 2018-03-21 20:19 GXZlegend 阅读(...) 评论(...) 编辑 收藏