Live2D

Solution -「Gym 102956A」Belarusian State University

Description

  Link.

  给定两个不超过 2n1 次的多项式 A,B,对于第 i[0,n) 个二进制位,定义任意一个二元加法 i:{0,1}×{0,1}{0,1},而对于两个整数 u,v[0,2n),定义 uv=i=0n1(uiivi)2i。求 A,B 卷积,保证答案任意系数不超过 2631

Solution

  可以看出这个问题不弱于 FWT,所以我们大概需要根据 FWT 的思路,来 DIY 一个变换。

  在 FWT 的框架下,枚举每个二进制位,对 16 种不同的加法分别构造各自的变换方式,构造时只需要考虑 (a0+a1x)(b0+b1x) 的卷积,使得这个卷积合法即可。

  复杂度 O(2nn)

Code

  不要用 switch!不要用 switch!不要用 switch!这个语法真的离谱。

  啊……极少地在代码里爆了粗口,以记录我分类讨论加上被 switch 弄傻的愉悦!(

/*~Rainybunny~*/

#include <cstdio>
#include <cassert>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

typedef long long LL;

const int MAXN = 18, MAXL = 1 << MAXN;
int n;
LL a[MAXL + 5], b[MAXL + 5];
char op[MAXN + 5][4];

inline int type( const char* o ) {
    int ret = 0;
    per ( i, 3, 0 ) ret = ret << 1 | ( o[i] ^ '0' );
    return ret;
}

inline void fuckin_wa_tle( const int len, LL* u, const int tp ) {
    // { -1: first item, 0: result, 1: second item }.
#define swp( a, b ) void( a ^= b ^= a ^= b )
    for ( int i = 0, stp = 1; stp < len; ++i, stp <<= 1 ) {
        for ( int j = 0; j < len; j += stp << 1 ) {
            rep ( k, j, j + stp - 1 ) {
                LL &p = u[k], &q = u[k + stp];
                switch ( type( op[i] ) ) {
                    // what fuckin stupid grammar??? I'll never `switch` again.
                    case 0:
                        if ( !~tp ) p += q, q = 0;
                        else if ( tp ) p += q, q = 0;
                        break;
                    case 1:
                        if ( !~tp ) swp( p, q ), p += q;
                        else if ( tp ) swp( p, q ), p += q;
                        else p -= q;
                        break;
                    case 2:
                        if ( !~tp ) swp( p, q ), p += q;
                        else if ( tp ) p += q;
                        else p -= q;
                        break;
                    case 3:
                        if ( !~tp ) swp( p, q );
                        else if ( tp ) p = q = p + q;
                        break;
                    case 4:
                        if ( !~tp ) p += q;
                        else if ( tp ) swp( p, q ), p += q;
                        else p -= q;
                        break;
                    case 5:
                        if ( !~tp ) p = q = p + q;
                        else if ( tp == 1 ) swp( p, q );
                        break;
                    case 6:
                        p += q, q = p - 2 * q;
                        if ( !tp ) {
                            assert( !( p % 2 ) && !( q % 2 ) );
                            p /= 2, q /= 2;
                        }
                        break;
                    case 7:
                        if ( !~tp ) swp( p, q ), q += p;
                        else if ( tp ) swp( p, q ), q += p;
                        else q -= p;
                        break;
                    case 8:
                        if ( !~tp ) p += q;
                        else if ( tp ) p += q;
                        else p -= q;
                        break;
                    case 9:
                        q += p, p = q - 2 * p;
                        if ( !tp ) {
                            assert( !( p % 2 ) && !( q % 2 ) );
                            p /= 2, q /= 2;
                        }
                        break;
                    case 10:
                        if ( !~tp ) p = q = p + q;
                        break;
                    case 11:
                        if ( !~tp ) swp( p, q ), q += p;
                        else if ( tp ) q += p;
                        else q -= p;
                        break;
                    case 12:
                        if ( tp == 1 ) p = q = p + q;
                        break;
                    case 13:
                        if ( !~tp ) q += p;
                        else if ( tp ) swp( p, q ), q += p;
                        else q -= p;
                        break;
                    case 14:
                        if ( !~tp ) q += p;
                        else if ( tp ) q += p;
                        else q -= p;
                        break;
                    case 15:
                        if ( !~tp ) q += p, p = 0;
                        else if ( tp ) q += p, p = 0;
                        break;
                    default: assert( false );
                }
            }
        }
    }
#undef swp
}

int main() {
    scanf( "%d", &n );
    rep ( i, 0, n - 1 ) scanf( "%s", op[i] );
    rep ( i, 0, ( 1 << n ) - 1 ) scanf( "%lld", &a[i] );
    rep ( i, 0, ( 1 << n ) - 1 ) scanf( "%lld", &b[i] );

    fuckin_wa_tle( 1 << n, a, -1 ), fuckin_wa_tle( 1 << n, b, 1 );
    rep ( i, 0, ( 1 << n ) - 1 ) a[i] *= b[i];
    fuckin_wa_tle( 1 << n, a, 0 );

    rep ( i, 0, ( 1 << n ) - 1 ) {
        printf( "%lld%c", a[i], i < repi ? ' ' : '\n' );
    }
    return 0;
}

posted @   Rainybunny  阅读(121)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示