• ZOJ 3690 Choosing number(矩阵)


    Choosing number

    【题目链接】Choosing number

    【题目类型】矩阵

    &题解:

    这题就和已经dp极像了,所以找方程就很困难了.可以这样找:
    设f(n)是前n-1个人已经完成,第n个人选>k,g(n)是前n-1个人已经完成,第n个人选<=k.
    那么f(n)=f(n-1)*(m-k)+g(n-1)*(m-k) g(n)=f(n-1)*k+g(n-1)*(k-1)
    最后答案是f(n)+g(n) 所以这题难就难在想公式上

    【时间复杂度】(O(logn))

    &代码:

    #include <cstdio>
    #include <bitset>
    #include <iostream>
    #include <set>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <vector>
    using namespace std;
    #define INF 0x3f3f3f3f
    typedef long long ll;
    const int M= 1000000007;
    ll n,m,k;
    struct mat
    {
    	ll m[4][4];
    }A;
    mat Mul(mat a,mat b)
    {
    	mat c;
    	for(int i=0;i<2;i++){
    		for(int j=0;j<2;j++){
    			c.m[i][j]=0;
    			for(int k=0;k<2;k++){
    				c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%M;
    			}
    		}
    	}
    	return c;
    }
    mat bPow(mat a,ll z)
    {
    	mat un;
    	for(int i=0;i<2;i++)for(int j=0;j<2;j++)
    	un.m[i][j]=(i==j);
    	while(z){
    		if(z&1)
    			un=Mul(un,a);
    		a=Mul(a,a);
    		z>>=1;
    	}
    	return un;
    }
    int tb[4];
    void Init()
    {
    	tb[0]=m-k,tb[1]=k;
    	A.m[0][0]=A.m[0][1]=m-k;
    	A.m[1][0]=k,A.m[1][1]=k-1;
    }
    int main()
    {
    	freopen("E:1.txt","r",stdin);
    	while(cin>>n>>m>>k){
    		Init();
    		A=bPow(A,n-1);
    		ll ans=0;
    		for(int i=0;i<2;i++)
    		for(int j=0;j<2;j++){
    			ans=(ans+A.m[i][j]*tb[j])%M;
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    快速指引(CDH6.3.2)
    gRpc 跨语言调用(NetCore 与 Spring Boot)
    Windows 极简利器
    Jenkins 于Docker 中源配置
    Kettle 问题
    在 Ubuntu 下直接将二进制文件制作成 rpm 包
    麒麟常见问题
    基于jssip的简单封装
    带有handleEvent的eventEmitter
    js集锦
  • 原文地址:https://www.cnblogs.com/s1124yy/p/6667073.html
Copyright © 2020-2023  润新知