zoukankan      html  css  js  c++  java
  • HDU5564 Clarke and digits

    前置知识

    (dp[i][j][k])表示(i)长,(mod7=j),这个位置选了(k)的方案数。

    (dp[i+1][(j*10+x)mod7][x]+=dp[i][j][y];//x+y!=K​)

    (Ma.a[i][j]=1)表示(i)状态->(j)状态可以转移

    如果设(ans=qkpow(Ma,K))

    (ans.a[i][j])表示走(K)步之后状态(i)到状态(j)的方案数。

    如果对这个不熟悉可以看看HDU5607

    题解

    然后对于本题而言,就要构建转移的矩阵。

    注意到对于后两维而言,其实他们的转移都是一样的,与(i)没有关系,而且其状态只有7*10,所以可以构建(70·70)的转移矩阵。

    初始矩阵就是第一位随便填哪个数字都无所谓,所以

    for(int i=1;i<10;i++)
    	s.a[0][st(i%7,i)]=1;
    

    接下来还有一个问题:如何统计前缀和?

    我们要求的不仅仅是(ans(R),ans(L))而是(sum_{i=L}^Rans(i))

    所以,这里有一个巧妙的操作:

    for(int i=0;i<10;i++)
        Ma.a[i][70]=1;
    Ma.a[70][70]=1;
    

    这样就可以保证我们最后要求的(ans=sum_{i=0}^9a[0][i])每一层都会被加到70这个点上,所以最后(a[0][70])就是答案。

    代码

    #include<bits/stdc++.h>
    #define M 105
    using namespace std;
    const int mod=1e9+7;
    int l,r,K,T;
    struct Matrix{
        int n,m,a[M][M];
        void clear(){memset(a,0,sizeof(a));}
        void resize(int _n,int _m){n=_n;m=_m;}
        Matrix operator *(const Matrix &_)const{
            Matrix res;res.resize(n,_.m);
            for(int i=0;i<=n;i++){
                for(int j=0;j<=_.m;j++){
                    res.a[i][j]=0;
                    for(int k=0;k<=m;k++){
                        res.a[i][j]+=1LL*a[i][k]*_.a[k][j]%mod;
                        if(res.a[i][j]>=mod)res.a[i][j]-=mod;    
                    }
                }
            }
            return res;
        }
    }Ma,s;
    Matrix qkpow(Matrix a,int b){
        Matrix res;res.clear();res.resize(a.n,a.n);
        for(int i=0;i<=a.n;i++)res.a[i][i]=1;
        while(b){if(b&1)res=res*a;a=a*a;b>>=1;}
        return res;
    }
    int st(int i,int j){return i*10+j;}
    int main(){
    	cin>>T;
    	s.clear();s.resize(70,70);
    	for(int i=1;i<10;i++)
    		s.a[0][st(i%7,i)]=1;
    	while(T--){
    		scanf("%d%d%d",&l,&r,&K);
    		Ma.clear();Ma.resize(70,70);
    		for(int y=0;y<10;y++){
    			for(int x=0;x<10;x++){
    				if(x+y==K)continue;
    				for(int j=0;j<7;j++){
    					Ma.a[st(j,y)][st((j*10+x)%7,x)]=1;
    				}
    			}
    		}
    		for(int i=0;i<10;i++)
    			Ma.a[i][70]=1;
    		Ma.a[70][70]=1;
    		Matrix R=s*qkpow(Ma,r);
    		Matrix L=s*qkpow(Ma,l-1);
    		printf("%d
    ",(R.a[0][70]-L.a[0][70]+mod)%mod);
    	}
    	return 0;
    }
    
  • 相关阅读:
    【和我一起学python吧】Python安装、配置图文详解
    【和我一起学python吧】初学Python,版本如何选择?
    CSS使用简介
    css样式表中的样式覆盖顺序
    转载-ActiveMQ通过JAAS实现的安全机制
    消息队列开发记录笔记-ActiveMQ
    转载-使用消息队列的 10 个理由
    在linux或mac终端下将命令结果输出到文件保存
    ideviceinstaller命令(类似android的adb)
    mac安装mysql及导库
  • 原文地址:https://www.cnblogs.com/zryabc/p/10392620.html
Copyright © 2011-2022 走看看