题目链接

题意 :

给你一个a数组和b数组,构造出A[i][j]矩阵(A[i][j] = a[i xor j])

给出等式 A * x = b ( mod p )

n等于4的时候有:

A[0][0]*x[0] + A[0][1]*x[1] + A[0][2]*x[2] + A[0][3]*x[3] = b[0] (mod p)
A[1][0]*x[0] + A[1][1]*x[1] + A[1][2]*x[2] + A[1][3]*x[3] = b[1] (mod p)
A[2][0]*x[0] + A[2][1]*x[1] + A[2][2]*x[2] + A[2][3]*x[3] = b[2] (mod p)
A[3][0]*x[0] + A[3][1]*x[1] + A[3][2]*x[2] + A[3][3]*x[3] = b[3] (mod p)

分析 :

对于给出的矩阵乘法式子、你随便取出第一行会发现一个规律

例如 A[0][0]*x[0] + A[0][1]*x[1] + A[0][2]*x[2] + A[0][3]*x[3] = b[0] (mod p)

A[0][0]*x[0] => a[0^0] * x[0] => a[0] * x[0] = b[0]

A[0][1]*x[1] => a[0^1] * x[1] => a[1] * x[1] = b[0]

......

然后你会发现当把所有的 A[i][j] 变成 a[i^j] 后

每一条恒等式都变成了异或卷积的形式

当然这个规律也可以这么看,你会发现 A 的第二维下标永远和 x 的下标一样

所以变成卷积形式的话,那么的出来的异或值永远为 i ==> A[i][j] * x[j] + A[i][j+1]*x[j+1] + .... = b[i] ==> i^j^j = i

所以可以用 FWT 思考

对于普通的 FWT 优化的是

for(int i=0; i<n; i++) for(int j=0; j<n; j++) b[i^j] += a[i] * x[j]

这里我们已知 a 和 b 要求 x、可以将下标变化一下有

for(int i=0; i<n; i++) for(int j=0; j<n; j++) b[i] += a[j] * x[j^i]

for(int i=0; i<n; i++) for(int j=0; j<n; j++) x[i^j] += b[i] / a[j]

这样就变成了熟悉的异或卷积的形式

只不过乘法运算变成了除法运算、这里还好是求模意义下的

故可以用乘法逆元来将除法变成乘法

for(int i=0; i<n; i++) for(int j=0; j<n; j++) x[i^j] = b[i] * inv_a[j]

这题就做完了

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;
;
LL inv2 = (mod + )>>;

void FWT(LL f[], int n, int op) {
    ;
    while((1LL<<mx) < n) mx++;
    ; i <= mx; ++i) {
         << i), len = m >> ;
        ; r < n; r += m) {
            int t1 = r, t2 = r + len;
            ; j < len; ++j, ++t1, ++t2) {
                LL x1 = f[t1], x2 = f[t2];
                ) {   //xor
                    f[t1] = x1 + x2;
                    f[t2] = (x1 - x2 + mod) % mod;
                    if(f[t1] >= mod) f[t1] -= mod;
                    ) f[t2] += mod;
                }
                ) {   //and
                    f[t1] = x1 + x2;
                    f[t2] = x2;
                    if(f[t1] >= mod) f[t1] -= mod;
                }
                ) {   //or
                    f[t1] = x1;
                    f[t2] = x2 + x1;
                    if(f[t2] >= mod) f[t2] -= mod;
                }
            }
        }
    }
}
void IFWT(LL f[], int n, int op) {
    ;
    while((1LL<<mx) < n) mx++;
    ; --i) {
         << i), len = m >> ;
        ; r < n; r += m) {
            int t1 = r, t2 = r + len;
            ; j < len; ++j, ++t1, ++t2) {
                LL x1 = f[t1], x2 = f[t2];
                ) {   //xor
//                    f[t1] = (x1 + x2) / 2;
//                    f[t2] = (x1 - x2) / 2;
                    f[t1] = (x1 + x2) * inv2;
                    f[t2] = (x1 - x2) * inv2;
                    if(f[t1] >= mod) f[t1] %= mod;
                    if(f[t2] >= mod) f[t2] %= mod;
                    ) f[t2] = f[t2] % mod + mod;
                }
                ) {   //and
                    f[t1] = x1 - x2;
                    f[t2] = x2;
                    ) f[t1] += mod;
                }
                ) {   //or
                    f[t1] = x1;
                    f[t2] = x2 - x1;
                    ) f[t2] += mod;
                }
            }
        }
    }
}

LL pow_mod(LL a, LL b){
    a %= mod;
    LL ret = ;
    while(b){
        ) ret = (ret * a)%mod;
        a = (a * a)%mod;
        b >>= ;
    }return ret;
}

 + ;
LL a[maxn], b[maxn], x[maxn];

int main(void){__stTIME();__IOPUT();

    int n;
    sci(n);

    ; i<n; i++) scl(a[i]);
    ; i<n; i++) scl(b[i]);

    FWT(a, n, );
    FWT(b, n, );

    ; i<n; i++) x[i] = (b[i] * pow_mod(a[i], mod-))%mod;

    IFWT(x, n, );

    ; i<n; i++) printf("%lld\n", x[i]);

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

Nowcoder Circulant Matrix ( FWT )的更多相关文章

  1. 2018牛客网暑期ACM多校训练营(第九场)A -Circulant Matrix(FWT)

    分析 大佬说看样例就像和卷积有关. 把题目化简成a*x=b,这是个xor的FWT. FWT的讲解请看:https://www.cnblogs.com/cjyyb/p/9065615.html 那么要求 ...

  2. Toeplitz matrix 与 Circulant matrix

    之所以专门定义两个新的概念,在于它们特殊的形式,带来的特别的形式. 1. Toeplitz matrix 对角为常数: n×n 的矩阵 A 是 Toepliz 矩阵当且仅当,对于 Ai,j 有: Ai ...

  3. Nowcoder Playing Games ( FWT 优化 DP && 博弈论 && 线性基)

    题目链接 题意 : 给出 N 个数.然后问你最多取出多少石子使得在 NIM 博弈中.后手必胜 分析 :  Nim 博弈模型,后手必胜当且仅当各个堆的石子的数目的异或和为 0 转化一下.变成最少取多少石 ...

  4. Nowcoder Monotonic Matrix ( Lindström–Gessel–Viennot lemma 定理 )

    题目链接 题意 : 在一个 n * m 的矩阵中放置 {0, 1, 2} 这三个数字.要求 每个元素 A(i, j) <= A(i+1, j) && A(i, j) <= ...

  5. 《DSP using MATLAB》Problem5.33

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  6. 《DSP using MATLAB》Problem 5.31

    第3小题: 代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Out ...

  7. 《DSP using MATLAB》Problem 5.30

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  8. 《DSP using MATLAB》Problem 5.28

    昨晚手机在看X信的时候突然黑屏,开机重启都没反应,今天维修师傅说使用时间太长了,还是买个新的吧,心疼银子啊! 这里只放前两个小题的图. 代码: 1. %% ++++++++++++++++++++++ ...

  9. 《DSP using MATLAB》Problem 5.24-5.25-5.26

    代码: function y = circonvt(x1,x2,N) %% N-point Circular convolution between x1 and x2: (time domain) ...

随机推荐

  1. PTA(Advanced Level)1036.Boys vs Girls

    This time you are asked to tell the difference between the lowest grade of all the male students and ...

  2. windows10专业版激活

    [1]右击我的电脑->属性,查看激活情况 [2]管理员身份打开CMD [2.1]如果不知道CMD是什么东西 [2.2]如果上面那个也找不到,直接按windows键(就是ctrl和alt中间那个键 ...

  3. hashMap怎样解决hash冲突

    通过链表的方式处理: java1.7是单向链表 jvav1.8在数量小于8时是单向链表,大于8就是红黑树,查找方式遍历判断 解决冲突的方式很多,例如再hash,再散列(开放地址法,探测再散列)

  4. Ubuntu 系统安装 Docker

    安装 Docker CE 有多种方法,下面是最简单的通过Docker仓库的安装方法,其他方法参见官方文档. 设置仓库 刷新软件包 sudo apt-get update 安装必要的软件包 sudo a ...

  5. windows下一步到位搭建pycharm的开发环境

    pycharm的开发环境主要涉及到以下三个方面 pycharm的激活 这里采用破解的方式来达到永久激活的目的,因为激活码用着用着就过期的你,会发现不厌其烦的 通过测试,这个破解包适用于2017-201 ...

  6. MySQL 的索引是什么?怎么优化?

    索引类似大学图书馆建书目索引,可以提高数据检索的效率,降低数据库的IO成本.MySQL在300万条记录左右性能开始逐渐下降,虽然官方文档说500~800w记录,所以大数据量建立索引是非常有必要的.My ...

  7. yii的多表查询

    获取用户发布消息的指定消息id的总和点赞数 Yii $productIds = ['2260', '2262', '2263', '2268', '2269']; $plSql = Like::fin ...

  8. countUp.js-数字滚动效果(简单基础使用)

    最近写了个移动端宣传页,里面有数字的效果,所以有使用到countUp.js. 以下内容有包括:h5页面countUp.js的引入和实例.参数说明.事件简单使用和描述.countUp.js源代码. 附上 ...

  9. javaweb中的标签的核心标签库的常用标签

    //标签的使用使得页面的代码更加简洁,jsp脚本的尽可能少的使用,所以熟练掌握标签对于开发是很有必要的 <%--set设置数据,默认在page域 --%> <c:set var=&q ...

  10. symfony3 yml配置文件详解

    AppBundle\Entity\BlogComment: //映射实体    type: entity   //类型    repositoryClass: AppBundle\Repository ...