列表

详情


NC251502. lonely

描述

题目背景

わたし わたし わたしはここにいる

我 我 我就在这里

殴り書きみたいな音出せない状態で叫んだよ

在无法发出杂乱音色的情况下我选择了呐喊

なんかに なりたい なりたい 何者かでいい

想要成为 成为 成为什么人都好

馬鹿なわたしは歌うだけ

愚蠢的我唯有放声高歌

ぶちまけちやおうか星に

对着星星都宣泄出来吧


题意描述

给出 n 个点,对于每个非空点集 S,给出权值 a_S 和贡献值 b_S,其中 a,b 下标是用二进制表示的集合。

f_{S,i} 表示把 S 分成 i 个不交非空集合,集合权值之积之和。对于 i=1\sim n,求 \sum _{S=0}^{2^n-1}b_Sf_{S,i}

输入描述

第一行一个整数 n

接下来一行 2^n-1 个数,依次表示 a_1,a_2,\cdots,a_{2^n-1}

接下来一行 2^n-1 个数,依次表示 b_1,b_2,\cdots,b_{2^n-1}

输出描述

输出一行 n 个数依次表示答案对 998244353 取模的值。

示例1

输入:

3
4 2 1 5 3 5 1
3 1 1 3 3 3 1

输出:

55 129 40

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 3179ms, 内存消耗: 185072K, 提交时间: 2023-08-12 10:17:25

#include <bits/stdc++.h>
#define FOR(i, l, r) for(int i = (l); i <= (r); i++)
#define ROF(i, r, l) for(int i = (r); i >= (l); i--)
#define sz(a) int((a).size())
#define vi vector<int>
#define ll long long
#define LL __int128
#define ull unsigned long long
using namespace std;
const int N = 20,P=998244353;
const ll lim = (ull)P * P * 15;
int n;
int a[1 << N], b[1 << N], c[1 << N];
int f[N+1][1<<N],g[N+1][1<<N];
int ans[N+1];
int dp1[N+1],dp2[N+1];
ull tmp[N+1];
int power(int a, int b, int c = 1) {
    for(; b; b >>= 1, a = (ll)a * a % P) if(b & 1) c = (ll)c * a % P;
    return c;
}
void FWT(int a[], int t) {
    t = (t + P) % P;
    for(int i = 2; i <= (1 << n); i <<= 1) {
        for(int j = 0; j < (1 << n); j += i) {
            for(int k = 0; k < (i>>1);k++) {
                (a[j+k+(i>>1)]+=(ll)a[j+k]*t%P)%=P;
            }
        }
    }

}
int main() {
    ios :: sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    int full=(1<<n)-1;
    FOR(i, 1, (1 << n) - 1) cin >> a[i];
    FOR(i, 1, (1 << n) - 1) cin >> b[i];
    FOR(i, 1, (1 << n) - 1) c[i] = c[i >> 1] + (i & 1);
    FOR(i,1,(1<<n)-1){
        g[c[i]][i]=a[i];
        int ri=i^full;
        f[c[ri]][ri]=b[i];
    }
    FOR(i,0,n)FWT(f[i],1),FWT(g[i],1);
    FOR(i,0,(1<<n)-1){
        FOR(j,0,n)dp1[j]=f[j][i],dp2[j]=g[j][i];
        FOR(j,0,n-1){
            FOR(k,0,n)tmp[k]=0;
            ROF(k,n,j){
                FOR(l,1,n-k){
                    tmp[k+l]+=(ll)dp1[k]*dp2[l];
                    if(tmp[k+l]>=lim)tmp[k+l]%=P;
                }
            }
            FOR(k,0,n)dp1[k]=tmp[k]%P;
            int op = c[full ^ i] & 1;
            if(op) (ans[j+1]+=P-dp1[n])%=P;
            else (ans[j+1]+=dp1[n])%=P;
        }
    }
    int ifac=1;
    FOR(i,1,n){
        ifac=(ll)ifac*power(i,P-2)%P;
        cout<<(ll)ans[i]*ifac%P<<" ";
    }
    cout << "\n";
}

上一题