zoukankan      html  css  js  c++  java
  • 【NOI OL #3】魔法值

    题目链接

    设$f_{i,u}$表示第$i$天$u$城市的魔法值。写一下式子:$$f_{i,u}=igopluslimits_{(u,v)} f_{i-1,v}$$

    其中$igoplus$表示连续异或。

    然后考虑加入邻接矩阵$g_{u,v}$取代枚举出边:$$f_{i,u}=igopluslimits_{v=1}^n f_{i-1,v} imes g_{u,v}$$

    然后我们发现,这是个异或的矩阵乘法。

    设$F_i$表示第$i$天的各城市魔法值的向量,$G$表示邻接矩阵,定义异或和$$(Aoplus B)_{i,j}=igopluslimits_{t=1}^k A_{i,t} imes B_{t,j}$$

    那么$$egin{matrix}F_i=F_0oplus &underbrace{Goplus Goplus cdots oplus G}\&i个Gend{matrix}$$

    考虑矩阵快速幂。先证一下结合律,即求证:$$Aoplus Boplus C=Aoplus (Boplus C)$$

    写一下式子:设$A$是$n imes p$矩阵,$B$是$p imes q$矩阵,$C$是$q imes m$矩阵,它们的异或和是$n imes m$矩阵。

    $$(Aoplus Boplus C)_{i,j}=igopluslimits_{x=1}^q (igopluslimits_{y=1}^p A_{i,y} imes B_{y,x}) imes C_{x,j}$$

    注意:一般来说,异或对乘法是没有分配率的,例如$3 imes(1oplus 2)=9 e (3 imes 1)oplus (3 imes 2)=5$。

    但是注意到$C$矩阵一定是一个$01$矩阵(显然,如果一些$01$矩阵进行异或和运算,只有乘法和异或,结果一定也还是$01$矩阵),它拆括号乘进去,不管$C_{x,j}$是$0$还是$1$,整个式子的值都不会发生变化。

    那么得到$$(Aoplus Boplus C)_{i,j}=igopluslimits_{x=1}^qigoplus limits_{y=1}^p A_{i,y} imes B_{x,y} imes C_{x,j}$$

    同理,对于$Aoplus(Boplus C)$,也可以同样写出式子去括号得到相同的结果,因此两者相等。也即,当$C$是$01$矩阵时,异或和运算满足结合律。

    那么$$F_i=F_0oplus G^i$$

    其中$G^i=igopluslimits_{j=1}^i G$。

    考虑到$F_0oplus G$的时间复杂度是$O(n^2)$,而$Goplus G$的时间复杂度是$O(n^3)$,因此如果我们对于每次询问都跑一遍矩阵快速幂的话,时间复杂度是$O(n^3qlog a)$,期望得分40分。

    那我们考虑预处理出所有$G^{2^k}$,每次询问对$a_i$进行二进制拆分,用$F_0$异或一些$G^{2^k}$,时间复杂度是$O(n^3log a)-O(n^2qlog a)$,可以得到满分。

    这里$O(f_1)-O(f_2)$表示,预处理时间复杂度为$O(f_1)$,其余时间复杂度为$O(f_2)$。

    还有就是,$2^{32}-1=4,294,967,295$,它比$INT\_MAX$的$2,147,483,647$要大。自闭了。

    代码(100分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define IL inline
    #define RG register
    #define _1 first
    #define _2 second
    using namespace std;
    typedef long long LL;
    const int N=100;
    const int L=32;
    
        int n,m,q;
        LL a[N+3];
        
    struct Mtx{
        int n,m;
        LL a[N+3][N+3];
        
        Mtx(int n=0,int m=0)
            :n(n),m(m){}
        
        IL Mtx operator*(Mtx b){
            Mtx c(n,b.m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=b.m;j++){
                    c.a[i][j]=0;
                    for(int k=1;k<=m;k++)
                        c.a[i][j]^=a[i][k]*b.a[k][j];
                    
                }
            return c;
            
        }
        
    }g[L+3],f;
    
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        for(int i=1,u,v;i<=m;i++){
            scanf("%d%d",&u,&v);
            g[0].a[u][v]=g[0].a[v][u]=1;
            
        }
        
        g[0].n=g[0].m=n;
        for(int i=1;i<L;i++)
            g[i]=g[i-1]*g[i-1];
        
        f.n=1;    f.m=n;
        for(LL x;q;q--){
            scanf("%lld",&x);
            memcpy(f.a[1]+1,a+1,n*sizeof(LL));
            for(int j=0;j<L;j++)
            if((x>>j)&1)
                f=f*g[j];
            printf("%lld
    ",f.a[1][1]);
            
        }
    
        return 0;
    
    }
    View Code
  • 相关阅读:
    【反射】Java反射机制
    Composer教程之常用命令
    Composer教程之基础用法
    Composer教程之初识Composer
    Composer 的结构详解
    现代 PHP 新特性系列(七) —— 内置的 HTTP 服务器
    现代 PHP 新特性系列(一) —— 命名空间
    现代 PHP 新特性系列(二) —— 善用接口
    现代 PHP 新特性系列(三) —— Trait 概览
    现代 PHP 新特性系列(四) —— 生成器的创建和使用
  • 原文地址:https://www.cnblogs.com/Hansue/p/12961108.html
Copyright © 2011-2022 走看看