zoukankan      html  css  js  c++  java
  • Luogu P3758 可乐

    Luogu P3758 可乐

    本题是一个经典的矩阵快速幂好题。

    但与其他题不一样的是,这个题的数据范围给的提示不是特别明显。其他题,如 POJ3735 中,(mleq 10^{10}),就是一个鲜明的提示。而此题中,(tleq 10^6),不算典型举证快速幂的数据范围,但也卡住了普通矩阵连乘的时间复杂度。

    从题面中他可以留在原地,或随机前往一个相邻的点,这个条件其实可以看出用的是矩阵快速幂(有点像 P6569 [NOI Online #3 提高组] 魔法值),问题就是如何处理自爆。

    我们从问题的本质出发来思考这个问题。

    自爆,其实就是打断了他的双腿,不能再走动了。对啊!我们可以设置一个点 (n+1),命名为自爆点,可乐到了这里就要再也出不去了,也就是说,每个点都可以通向 (n+1),但是到了 (n+1) 这个点,就再也不能往外走了,即在 (n+1) 这个点形成了自环。

    如果上述描述有点抽象,我们那样例赖建一个矩阵,如下:

    [egin{bmatrix}1&1&0&1\1&1&1&1\0&1&1&1\0&0&0&1end{bmatrix} ]

    快速幂计算,最后将第一行的答案累加起来即可。记得取模

    //Don't act like a loser.
    //You can only use the code for studying or finding mistakes
    //Or,you'll be punished by Sakyamuni!!!
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    
    const int MAXN=40,mod=2017;
    
    int n,m,t;
    
    struct matrix {
    	long long data[MAXN][MAXN];
    	int col,row;
    	
    	void clear() {
    		col=row=0;
    		for(int i=0;i<MAXN;i++) {
    			for(int j=0;j<MAXN;j++) {
    				data[i][j]=0;
    			}
    		}
    	}
    	void initialize() {
    		clear();
    		col=row=n+1;
    		for(int i=1;i<=n+1;i++) {
    			data[i][i]=1;
    		}
    	}
    	
    	inline matrix operator *(matrix& b)const {
    		matrix ret;
    		ret.clear();
    		
    		for(int i=1;i<=col;i++) {
    			for(int k=1;k<=row;k++) {
    				if(data[i][k]==0) continue;
    				for(int j=1;j<=b.row;j++) {
    					ret.data[i][j]+=data[i][k]*b.data[k][j]%mod;
    					ret.data[i][j]%=mod;
    				}
    			}
    		}
    		ret.col=col;
    		ret.row=b.row;
    		return ret;
    	}
    };
    
    matrix ans;
    matrix opt;
    
    inline void qpow(int y) {
    	while(y) {
    		if(y&1) {
    			ans=ans*opt;
    		}
    		opt=opt*opt;
    		y>>=1;
    	}
    }
    
    signed main() {
    	cin>>n>>m;
    	opt.initialize();
    	for(int i=1;i<=n;i++) {
    		opt.data[i][n+1]=1;
    	} 
    	for(int i=1;i<=m;i++) {
    		int u,v;
    		cin>>u>>v;
    		opt.data[u][v]=opt.data[v][u]=1;
    	}
    	ans.initialize();
    	opt.col=opt.row=n+1;
    	cin>>t;
    	qpow(t);
    	int tot=0;
    	for(int i=1;i<=n+1;i++) {
    		tot=(tot+ans.data[1][i])%mod;
    	}
    	cout<<tot<<endl;
    	return 0;
    }
    
  • 相关阅读:
    linux设置网关修改ip
    Linux Source命令及脚本的执行方式解析
    ARM9 S3C2440 定时器中断
    Linux下配置静态IP地址,设置DNS和主机名
    s3c2440外部中断操作
    vmware中为虚拟机添加硬盘空间
    『SHELL』SHELL脚本执行方式
    WCF开发的几个频骤
    MyEclipse下Axis2插件的下载和安装
    WCF系列(二) 使用配置文件构建和使用WCF服务
  • 原文地址:https://www.cnblogs.com/huayucaiji/p/LGP3758.html
Copyright © 2011-2022 走看看