zoukankan      html  css  js  c++  java
  • 常州Day4题解

    1. 高精度

    这题略水,字符串可过,还不加压位等,操作只有BitShift和add/sub,不过编程复杂度有些高.(输出都是二进制我能说些什么...)

    2. N皇后问题 (警告! 不是平时你见到的N皇后问题...是一道Hash的模拟题,N皇后的位置都给你了,就是统计)

    二级标题很详细了,搜索那些解N皇后问题的千万莫戳进来.

    3. Sam数

    一道比较有意思的题.

    题意是,给定一个k,求所有k位数中所有相邻两位数差都小于等于2的数.输出$mod{10^9+7}$

    说的不够明白.来个例子:

    $2134678$ 这是一个符合要求的7阶Sam数.

    $6987688$ 这个不符合,$left| 9-6 ight|=3>2$

    很明显,当$k=1$时输出$10$.

    当$k=2$时,很明显最高位不可为0.

    于是第一位只能为$1~9$.

    第二位呢?显然不可能是$0~10$.限制条件摆那儿呢!

    于是想到,第二位是$0$的时候有两种可能,即$10$和$20$.这是从第一位是$0,1,2$的地方推导来的.

    于是递推式很明显,$F[i,j]=sum_{n=j-2}^{j+2}F[i-1,n] ext{While n}in ext{0~9}$

    可是数据范围:

    $30\% kle 10^6,60\% kle 10^{12},100\% 10^{18}$

    吓,$10^6 cdot 10$都基本爆空间好么? 逗我呢?

    注意到每次递推只需用到前一次的结果,用滚动数组即可. 30分到手.

    但是,十的十八次位数这是要闹那样!!!

    车到山前必有路(话说我当时还没想到).

    注意这是线性递推.每次递推后的$F[i]$都是前一次值的线性组合($ ext{linear combination}$),而这事可以用矩阵乘法解决.矩阵乘法遵守结合率,可以使用二分快速幂在$O(log{n})$时间内求出.至于矩阵乘法的复杂度...他不会随着输入数据的上升而上升,$O(n^3)$中n恒等于10,即是常数时间,只是常数比较大.

    时间复杂度是$O(1000 cdot log(n))=O(log{n})$.

    矩阵方法详细参数:

    变换矩阵:

    $tr=left[ egin{array} {lcr}
    1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \
    1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \
    1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 0 \
    0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 \
    0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 \
    0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 \
    0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 \
    0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 \
    0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \
    0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1
    end{array} ight]$

    初始向量:

    $i=left[ egin{array} {lcr}
    0 \
    1 \
    1 \
    1 \
    1 \
    1 \
    1 \
    1 \
    1 \
    1
    end{array} ight]$

    递推结果为$c = tr^k cdot i$

    结果

    $$sum=sum_{i in c}c[i]$$

    注意随时求余.特判k=1.

    最后一题代码(前两题还要?自己写去..)

    #include "cstdio"
    #define modulo 1000000007
    #include "cstring"
    struct mat{
    	long long m[10][10],i,j,k,t;
    	void cpy(mat b){
    		for(i=0;i<10;++i)
    			for(j=0;j<10;++j)
    				m[i][j]=b.m[i][j];
    	}
    	void mul(mat a){
    		mat tempa;
    		for(i=0;i<10;++i){
    			for(j=0;j<10;++j){
    				t=0;
    				for(k=0;k<10;++k){
    					t+=m[k][i]*a.m[j][k];
    				}
    				tempa.m[i][j]=t % modulo;
    			}
    		}
    		cpy(tempa);
    	}
    	void toUnit(){
    		memset(m,0,sizeof(m));
    		for(i=0;i<10;++i){
    			m[i][i]=1;//unit in matrix computation,oops...
    		}
    	}
    } matt,tt;
    struct vect{
    	long long m[10],tm;
    	int i,j;
    	void mul(mat a){
    		for(i=0;i<10;++i){
    			tm=0;
    			for(j=0;j<10;++j){
    				tm+=m[i]*a.m[i][j];
    			}
    			m[i]=tm % modulo;
    		}
    	}
    } vec;
    long long n,ac;
    void fastPow(long long n){
    	if(n&1){
    		tt.cpy(matt);
    	}else{
    		tt.toUnit();
    	}
    	while(n>>=1){
    		matt.mul(matt);
    		if(n&1){
    			tt.mul(matt);
    		}
    	}
    }
    const long long pa[10]={0,1,1,1,1,1,1,1,1,1};
    const long long pb[10][10]={
    	{1,1,1,0,0,0,0,0,0,0},
    	{1,1,1,1,0,0,0,0,0,0},
    	{1,1,1,1,1,0,0,0,0,0},
    	{0,1,1,1,1,1,0,0,0,0},
    	{0,0,1,1,1,1,1,0,0,0},
    	{0,0,0,1,1,1,1,1,0,0},
    	{0,0,0,0,1,1,1,1,1,0},
    	{0,0,0,0,0,1,1,1,1,1},
    	{0,0,0,0,0,0,1,1,1,1},
    	{0,0,0,0,0,0,0,1,1,1}
    };
    int main(){
    	scanf("%lld",&n);
    	if(n==1){
    		printf("10
    ");
    		return 0;
    	}
    	memcpy(vec.m,pa,sizeof(pa));
    	memcpy(matt.m,pb,sizeof(pb));
    
    	fastPow(n-1);//幂次修正
    	vec.mul(tt);
    	ac=0;
    	for(int i=0;i<10;++i){
    		ac+=vec.m[i];
    	}
    	printf("%lld
    ",ac % modulo);
    	return 0;
    }
    
  • 相关阅读:
    WordPress后台添加侧边栏菜单
    Redis 使用多个数据库及密码配置
    datatable 修改点击列头进行排序顺序
    命令行客户端操作pg数据库常用操作
    pg 创建自增id
    让 PHP COOKIE 立即生效(不用刷新就可以使用)
    js cookie
    使用mysql监视器即命令行下的mysql
    javascript 获取键盘上的按键代码KeyCode
    吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
  • 原文地址:https://www.cnblogs.com/tmzbot/p/3913767.html
Copyright © 2011-2022 走看看