• 叶落归根(hometown)


    叶落归根(hometown)

    题目描述

    叶落归根——树叶从树根生发出来,凋落后最终还是回到树根。比喻事物总有一定的归宿。接下来是题目。

    给定一个n个点的有向图G(点的编号为1~n),一开始落叶(仅作为一个代号,你也可以当成是Alice、Bob、甲乙丙丁戊己庚辛壬癸…)会在G的某个点s上。总共有t个单位时间,每个单位时间落叶都必须通过一条当前所在点的出边到达下一个点(有时下一个点和当前点会是相同的)。

    需要注意的是,如果当前所在点没有任何出边,落叶就会在这个单位时间被迫离开这张图,并且我们认为落叶永远不会再回来了。

    你要做的是对于每一个起始点s以及每一个总时长t(1<=t<=Q且为整数)求出落叶在起始点为s且经过t单位时间后的位置也是s的方案数。

    两个方案不同,当且仅当两个方案中存在至少一个时刻落叶所经过的边不是图G中的同一条边。

    为了便于检验,只需要输出所有情况(即所有不同的起始点和总时长,一共n*Q种情况)的方案数对给定正整数P取模后的异或和即可——也就是说,假设所有情况的方案数分别是ans1、ans2、ans3……你要输出的就是(ans1 mod P) xor (ans2 mod P) xor (ans3 mod P)……

    输入

    第一行3个整数n、Q、P,分别表示图G的点数、总时长t的上限和给定的模数P

    接下来n行,每行n个整数,其中第i行第j个数表示图G中从i出发到j的单向边数目

    输出

    一行一个整数,表示所有情况的方案数对给定正整数P取模后的异或和

    样例输入

    2 2 1000000207
    2 3
    4 5

    样例输出

    50

    提示

    数据规模和约定

    对于前10%的数据:n=2,Q=20

    对于另外10%的数据:n=3,Q=12

    对于前50%的数据:n<=20

    对于100%的数据:1<=n<=100,P<=2^30,Q<=10000,对于任意一对(u,v),图G中从u到v的边数不超过2^30

    来源


    solution

    就是一个矩阵,问你1-Q次方的对角线的和。

    考虑枚举t(1<=t<=Q)

    n^3乘出显然不行了。

    那么可以分块。考虑令o=sqrt(n)

    预处理矩阵的1~o次方 和x*o 次方(1<=x<=o)

    那么每次相当于求对角线。n^2乘起来就行。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define maxn 10005
    using namespace std;
    int n,q,mod,o;
    ll ans,A[320][102][102],B[320][102][102];
    ll read(){
        int v=0;char ch;
        while(!isdigit(ch=getchar()));v=(v<<1)+(v<<3)+ch-48;
        while(isdigit(ch=getchar()))v=(v<<1)+(v<<3)+ch-48;
        return v;
    }
    int main(){
        cin>>n>>q>>mod;o=sqrt(q);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)A[1][i][j]=read();
        for(int x=2;x<=o;x++){
            for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
            for(int j=1;j<=n;j++){
                A[x][i][j]=(A[x][i][j]+A[x-1][i][k]*A[1][k][j])%mod;
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                B[1][i][j]=A[o][i][j];
        }
        int T=q/o+1;
        for(int x=2;x<=T;x++){
            for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
            for(int j=1;j<=n;j++){
                B[x][i][j]=(B[x][i][j]+B[x-1][i][k]*B[1][k][j])%mod;
            }
        }
        for(int i=1;i<=n;i++)A[0][i][i]=B[0][i][i]=1;
        for(int x=1;x<=q;x++){
            int t1=x/o,t2=x%o;
            for(int i=1;i<=n;i++){
                ll tmp=0;
                for(int k=1;k<=n;k++){
                    tmp=(tmp+A[t2][i][k]*B[t1][k][i])%mod;
                }
                ans=ans^tmp;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

     

  • 相关阅读:
    如何解决IOS 下固定定位fixed 失效问题?
    fixed定位按钮在底部,键盘弹起,按钮被顶上去
    js对象和jquery对象相互转换
    # js中substr、substring、indexOf、lastIndexOf的用法
    在新页面中返回到前一页浏览的历史位置
    vue-cli构建的项目中axios的请求方式及跨域处理
    搭建基于Express框架运行环境 及其启动方式
    微信小程序Page中data数据操作和函数调用
    linux的一些基本操作
    JavaScript对象
  • 原文地址:https://www.cnblogs.com/liankewei/p/10410267.html
Copyright © 2020-2023  润新知