HDU 6057 – Kanade’s convolution | 2017 Multi-University Training Contest 3

HDU 6057 – Kanade’s convolution | 2017 Multi-University Training Contest 3

大家好,又见面了,我是全栈君。

/*
HDU 6057 - Kanade's convolution [ FWT ]  |  2017 Multi-University Training Contest 3
题意:
	给定两个序列 A[0...2^m-1], B[0...2^m-1]
	求 C[0...2^m-1]	,满足:
		C[k] = ∑[i&j==k] A[i^j] * B[i|j]
	m <= 19
分析:
	看C[k]的形式与集合卷积的形式接近,故转化式子时主要向普通的集合卷积式方向靠
	与三种位运算都相关的结论是 : i^j + i&j = i|j
	设 x = i^j, y = i|j,则显然 k = y-x,且 k 与 x 互成关于 y 的补集,即 k = x^y 
	
	再来关心给定(x,y),符合 x = i^j, y = i|j的(i,j)对的数目
		注意到相同的位 i&j 是确定的,x = i^j 是i和j不同的位的数目,这部分谁是 0 谁是 1 不固定
			故(i,j)对的数目为 2^bits(x)

	此时重写原式: C[k] = ∑ [k == x^y] [k == y-x] A[x]*2^bits(x) * B[y]
	
	设 A'[x] = A[x]*2^bits(x)
	由于 [k == x^y],第二个条件 [k == y-x] 等价于 bits(k) == bits(y) - bits(x)
		C[k] = ∑ [k == x^y] [bits(k) == bits(x) - bits(y)] A'[x] * B[y]
	
	将 A,B,C三个数组按 bits 划分:
		C[bits(k)][k] = ∑ [k == x^y] A[bits(x)][x]*2^bits(x) * B[bits(y)][y]
	
	最后按不同的维度(bits)做 FWT即可
*/
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
const int N = 1<<20;
int rev2;
long long inv( long long a , long long m)
{
	if (a == 1) return 1;
	return inv(m%a, m) * (m - m/a) % m;
}
void FWT(int a[], int n) {
    for (int d = 1; d < n; d <<= 1)
        for (int m = d<<1, i = 0; i < n; i += m)
            for (int j = 0; j < d; j++)
            {
                int x = a[i+j], y = a[i+j+d];
                a[i+j] = (x+y) % MOD;
                a[i+j+d] = (x-y+MOD) % MOD;
            }
}
void UFWT(int a[], int n) {
    for (int d = 1; d < n; d <<= 1)
        for (int m = d<<1, i = 0; i < n; i += m)
            for (int j = 0; j < d; j++)
            {
                int x = a[i+j], y = a[i+j+d];
                a[i+j] = 1LL*(x+y) * rev2 % MOD;
                a[i+j+d] = (1LL*(x-y)*rev2 % MOD + MOD) % MOD;
            }
}
int a[20][N], b[20][N], c[20][N];
int bits[N];
int m, n;
void init()
{
    rev2 = inv(2, MOD);
    bits[0] = 0;
    for (int i = 1; i < N; i++) bits[i] = bits[i>>1] + (i&1);
}
int main()
{
    init();
    scanf("%d", &m);
    n = 1<<m;
    for (int i = 0; i < n; i++)
    {
        int x; scanf("%d", &x);
        a[bits[i]][i] = 1LL*x * (1<<bits[i]) % MOD;
    }
    for (int i = 0; i < n; i++)
    {
        int x; scanf("%d", &x);
        b[bits[i]][i] = x;
    }
    for (int i = 0; i <= m; i++) FWT(a[i], n);
    for (int i = 0; i <= m; i++) FWT(b[i], n);
    for (int i = 0; i <= m; i++)
        for (int j = i; j <= m; j++)
            for (int k = 0; k < n; k++)
            {
                c[j-i][k] = (c[j-i][k] + 1LL*a[i][k] * b[j][k] % MOD) % MOD;
            }
    for (int i = 0; i <= m; i++) UFWT(c[i], n);
    long long ans = 0, base = 1;
    for (int i = 0; i < n; i++)
    {
        ans = ( ans + c[bits[i]][i] * base % MOD ) % MOD;
        base = base * 1526 % MOD;
    }
    printf("%lld\n", ans);
}

  

转载于:https://www.cnblogs.com/nicetomeetu/p/7291383.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108268.html原文链接:https://javaforall.net

(0)
上一篇 2022年3月5日 下午9:00
下一篇 2022年3月5日 下午9:00


相关推荐

  • kali安装中文输入法(本人一遍成功)

    kali安装中文输入法(本人一遍成功)kali 中文输入法安装 以下所有操作在你已经换源的情况下完成 首先 安装 ibus 到系统中 apt getinstallib pinyin 安装中选择是否继续输入 Y 然后开始下载下载后在命令窗口输入 reboot 重启然后在右上角会出现语言的选项接下来就成功了

    2026年3月17日
    2
  • linux设置网络适配器

    linux设置网络适配器1 安装完虚拟机后 我们的电脑的适配器会多出两个 VMnet1 和 VMnet82 打开虚拟机设置的网络适配器 可以看到网络连接方式有 桥接 NAT 仅主机 3 其中桥接使用主机的适配器 NAT 使用 VMnet8 仅主机模式使用 VMnet14 一般我们使用桥接即可 但是主机不止有一块网络适配器 一般无线和有线网卡各一个 我们需要选择主机能用的适配器 设置方式如下

    2026年2月6日
    2
  • c++ 常量表达式_c++符号常量

    c++ 常量表达式_c++符号常量常量表达式主要是允许一些计算发生在编译时,即发生在代码编译阶段而不是代码运行阶段。这是很大的优化,因为如果有些事情可以在编译时做,那么它只会做一次,而不是每次程序运行时都计算。使用constexpr,你可以创建一个编译时的函数:constexprintgetConst(){ return3;}voidtest07(){ intarr[getConst()]={0}…

    2026年4月17日
    5
  • 程序员java_java多线程的实现方式

    程序员java_java多线程的实现方式引言:“作为一名工作了十五年的老程序员,我深知编程行业的不容易,不仅需要应对高强度的工作,还需要学习大量的技术知识,而且不像医生、律师这些知识相对稳定的行业越老越吃香,软件行业的技术每隔一段时间就会更新换代,让你清零,逼着你从头再来。所谓“活到老,学到老”,用到程序员身上再合适不过了。在不断学习的过程中,我“痛恨”那些采用bottom-up方式来讲解技术的资料和文章,一上来就是技术细节、安装步骤、配置方法,让初学者晕头转向、不知所云,看完了以后也不知道为什么有这个东西、解决了什么问题、它有什么来龙去

    2026年2月24日
    6
  • ABP系列教学目录——Abp框架之实操演练集合

    ABP系列教学目录——Abp框架之实操演练集合ABP 是 ASP NETBoilerpla ASP NET 样板项目 的简称 ASP NETBoilerpla 是一个用最佳实践和流行技术开发现代 WEB 应用程序的新起点 它旨在成为一个通用的 WEB 应用程序框架和项目模板 框架 ABP 是基于最新的 ASP NETCORE ASP NETMVC 和 WebAPI 技术的应用程序框架 并使用流行的框架和库 它提供了便于使用的授权 依赖注入 验证 异常处理 本地化 日志记录 缓存等常用功能 架构 ABP 实现了多层架构 领域层 应用层 基

    2026年3月19日
    2
  • linux redis命令客户端,Redis客户端与基本命令「建议收藏」

    linux redis命令客户端,Redis客户端与基本命令「建议收藏」一、Redis客户端1.Redis命令行客户端开启:src下开启服务端:./redis-server&客户端访问:./redis-cli[-h127.0.0.1-p6379]关闭:src下./redis-clishutdown进入客户端后执行shutdown2.Redis远程客户端RedisDesktopManager软件远程客户端连接Redis服务器需要…

    2022年6月10日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号