zoukankan      html  css  js  c++  java
  • XJOI 3879 怪兽繁殖

    题意

    (N) 种不同的怪兽,标号为 (1)(N)
    每天晚上,所有的怪兽都会死去,当一只怪兽死去的时候,它会生出一只或者多只怪兽,因此怪兽的数量从来不会减少
    给你一个字符数组表示每种怪兽死去的时候能生出哪些种类的怪兽
    假设第 (i) 个字符串为"2 3 3",表示第i只怪兽死的时候,1只2类型的怪兽和2只3类型的怪兽会生出来
    显然,怪兽的数量可能会是无穷大的,也有些时候会变成一个定值
    一开始你只有一只1类型的怪兽,你想要知道最终会有多少只怪兽,对 (1e9+7) 取模
    如果有无穷多只,输出 (-1)

    输入格式

    第一行输入一个整数 (n) 表示怪兽的种类数 ((1≤n≤50))
    接下来 (n) 行每行一个字符串由若干个数字构成
    意义见题面描述

    输出格式

    输出一个整数

    样例输入&输出

    样例1

    1
    1
    
    1
    

    样例2

    1
    1 1
    
    -1
    

    样例3

    3
    2
    3
    1
    
    1
    

    样例4

    4
    1
    2 4
    2
    2
    
    1
    

    样例5

    7
    2 2
    3
    4 4 4
    5
    6
    7 7 7 7
    7
    
    24
    

    样例6

    7
    2 3
    5 7
    2 4
    5
    6
    4
    7
    
    5
    

    样例7

    7
    2
    3
    6 4
    3 5
    2
    7
    2
    
    -1
    

    样例8

    5
    2
    3 4
    5
    5
    2
    
    -1
    

    分析

    本题输入很坑,用getchar或者stringstream+string+getline
    别忘开long long
    构造一张图 (G) ,若怪物 (i) 能繁殖出一只怪物 (j) ,则连边 (<i,j>) (有向边)

    1. dfs判环,dfs计算答案 ( ext{Time Limit Exceeded})

    若存在一个在环上的点,它的出度大于1,那么肯定会无限循环。
    用邻接矩阵存图,因为可能存在很多重边。

    #include<cstdio>
    #include<cstdlib>
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #define maxn 52
    #define maxm 2502
    #define mod 1000000007
    using namespace std;
    char ch;
    int read(int& x){
    	x=0;
    	while(ch>='0'&&ch<='9'){
    		x=(x<<3)+(x<<1)+ch-'0';
    		ch=getchar();
    	}
    	while(ch==' ')ch=getchar();
    	if(ch==EOF){
    		return 0;
    	}
    	if(ch=='
    '){
    		ch=getchar();
    		return 0;
    	}
    	return 1;
    }
    int n,g[maxn][maxn],st[maxn],top;
    bool oncyc[maxn],inst[maxn];
    void getcyc(int u){
    	st[++top]=u;
    	inst[u]=1;
    	int count=0;
    	for(int v=1;v<=n;v++){
    		if(!g[u][v])continue;
    		count+=g[u][v];
    		if(!inst[v]){
    			getcyc(v);
    		}
    		else{
    			int t;
    			for(t=top;st[t]!=v;t--);
    			for(int i=t;i<=top;i++){
    				oncyc[st[i]]=1;
    			}
    		}
    		if(oncyc[u]&&count>1){
    			printf("-1
    ");
    			exit(0);
    		}
    	}
    	top--;
    	inst[u]=0;
    }
    long long DFS(int u){
    	long long ret=0;
    	for(int v=1;v<=n;v++){
    		if(!g[u][v])continue;
    		if(oncyc[v]){
    			ret=(ret+g[u][v])%mod;
    			continue;
    		}
    		ret=(ret+DFS(v)*g[u][v]%mod)%mod;
    	}
    	return ret;
    }
    int main(){
    	while(ch<'0'||ch>'9')ch=getchar();
    	read(n);
    	for(int u=1;u<=n;u++){
    		int v;
    		bool tmp;
    		while(1){
    			tmp=read(v);
    			g[u][v]++;
    			if(!tmp)break;
    		}
    	}
    	getcyc(1);
    	printf("%lld
    ",DFS(1));
    	return 0;
    }
    

    2. 矩阵快速幂

    我们定义矩阵$$S=[1,0,0,...,0]$$
    (S) 长为 (1) ,宽为 (n)
    再定义矩阵 (A)(G) 的邻接矩阵
    我们发现,怪兽每繁殖一次,相当于做一次 (S=S* A) 的运算
    我们用矩阵快速幂,让 (S) 分别乘 (1e8)(2e8) 次得到矩阵 (R)(T) ,由于结果很大,所以要取模,多取几个模数,比较 (R)(T) 中元素之和是否相等。由于最后输出的答案需要取模 (1e9+7) ,所以把 (1e9+7) 放在最后取模。

    Code

    #include<cstdio>
    #pragma GCC optimize(2)
    #define maxn 52
    using namespace std;
    long long mod;
    long long Plus(long long a,long long b){
        long long ret=a+b;
        return ret>=mod?ret-mod:ret;
    }
    long long mul(long long a,long long b){
        return a*b%mod;
    }
    struct matrix{
        long long a[maxn][maxn];
        int n,m;
        matrix& operator =(const matrix& M){
            n=M.n,m=M.m;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    a[i][j]=M.a[i][j];
                }
            }
        }
        void init(int _n,int _m){
            n=_n,m=_m;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++)a[i][j]=0;
                a[i][i]=1;
            }
        }
        void init0(int _n=0,int _m=0){
            n=_n,m=_m;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    a[i][j]=0;
                }
            }
        }
        void output()const{
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    printf("%lld ",a[i][j]);
                }
                putchar('
    ');
            }
        }
    };
    const matrix mul(const matrix& a,const matrix& b){
        matrix ans;
        ans.init0(a.n,b.m);
        if(a.m!=b.n)return ans;
        for(int i=1;i<=a.n;i++){
            for(int j=1;j<=b.m;j++){
                ans.a[i][j]=0;
                for(int k=1;k<=a.m;k++){
                    ans.a[i][j]=Plus(ans.a[i][j],mul(a.a[i][k],b.a[k][j]));
                }
            }
        }
        return ans;
    }
    matrix qpow(matrix a,long long b){
        matrix ans;
        ans.init(a.n,a.m);
        while(b){
            if(b&1)ans=mul(ans,a);
            a=mul(a,a);
            b>>=1;
        }
        return ans;
    };
    matrix s,t,g;
    int n;
    namespace INIT{
        char ch;
        int read(int& x){
            x=0;
            while(ch>='0'&&ch<='9'){
                x=(x<<3)+(x<<1)+ch-'0';
                ch=getchar();
            }
            while(ch==' ')ch=getchar();
            if(ch==EOF){
                return 0;
            }
            if(ch=='
    '){
                ch=getchar();
                return 0;
            }
            return 1;
        }
        void init(){
            while(ch<'0'||ch>'9')ch=getchar();
            read(n);
            g.n=g.m=n;
            for(int u=1;u<=n;u++){
                int v;
                bool tmp;
                while(1){
                    tmp=read(v);
                    g.a[u][v]++;
                    if(!tmp)break;
                }
            }
        }
    }
    long long MOD[5]={0,19260817,1000000009,998244353,1000000007};
    int main(){
        INIT::init();
        long long ans1,ans2;
        for(int j=1;j<=4;j++){
            mod=MOD[j];
            s.init(1,n);
            s=mul(s,qpow(g,100000000));
            t.init(1,n);
            t=mul(t,qpow(g,200000000));
            ans1=ans2=0;
            for(int i=1;i<=n;i++)ans1=Plus(ans1,s.a[1][i]),ans2=Plus(ans2,t.a[1][i]);
            if(ans1!=ans2){
                puts("-1");
                return 0;
            }
        }
        printf("%lld
    ",ans1);
        return 0;
    }
    

    3. 强连通分量,缩点

    Unknown

    Code

    
    
  • 相关阅读:
    Python 操作 Azure Blob Storage
    @private、@protected与@public三者之间的区别
    iOS设计模式
    NSMapTable、NSHashTable与NSPointerArray的封装
    iOS设计模式
    用UITextView加载rtfd文件
    UIWebView如何加载本地图片
    [翻译] BezierString
    [翻译] AYVibrantButton
    用NSOperation写下载队列
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/9874634.html
Copyright © 2011-2022 走看看