zoukankan      html  css  js  c++  java
  • UVa 11651 Krypton Number System DP + 矩阵快速幂

    题意:

    有一个(base(2 leq base leq 6))进制系统,这里面的数都是整数,不含前导0,相邻两个数字不相同。
    而且每个数字有一个得分(score(1 leq score leq 10^9)),得分为 相邻两个数字之差的平方之和。

    给出(base)(score),求满足条件的整数的个数 (mod \, 2^{32})

    分析:

    首先考虑DP的做法:

    (dp(i, j))表示满足当前分数为(i)最后一个数字是(j)的数字的个数。
    递推就是枚举下一个数字(k),就有转移方程:
    (dp(i+d,k)=sum dp(i, j)),其中(k eq j)(d=(k-j)^2)
    这种方法的复杂度使(O(base^2 cdot score))的。

    考虑矩阵优化:

    因为状态转移中,能得到的最大分数是((base-1)^2),所以我们的转移矩阵只要保留前面((base-1)^2)(score)的信息就行了。
    用语言不方便表达,我举具体例子,
    (base=3)时,有如下转移:

    上面9行很好理解,就是一个错位。
    下面3行才是状态的转移。
    容易看出,我们的矩阵的边长最大会达到(6(6-1)^2=150)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef unsigned int LL;
    const int maxn = 150;
    
    int n, m, sz;
    
    struct Matrix
    {
    	LL a[maxn][maxn];
    	
    	Matrix() {
    		for(int i = 0; i < maxn; i++)
    			for(int j = 0; j < maxn; j++) a[i][j] = 0;
    	}
    	
    	Matrix operator * (const Matrix& t) const {
    		Matrix ans;
    		for(int i = 0; i < sz; i++)
    			for(int j = 0; j < sz; j++) if(a[i][j])
    				for(int k = 0; k < sz; k++)
    					ans.a[i][k] += a[i][j] * t.a[j][k];
    		return ans;
    	}
    };
    
    Matrix pow_mod(Matrix a, int n) {
    	Matrix ans;
    	for(int i = 0; i < sz; i++) ans.a[i][i] = 1;
    	while(n) {
    		if(n & 1) ans = ans * a;
    		a = a * a;
    		n >>= 1;
    	}
    	return ans;
    }
    
    LL a[maxn], dp[25][6];
    
    int main()
    {
    	int T; scanf("%d", &T);
    	for(int kase = 1; kase <= T; kase++) {
    		printf("Case %d: ", kase);
    		scanf("%d%d", &n, &m);
    		int N = (n - 1) * (n - 1) * n;
    
    		//DP
    		memset(dp, 0, sizeof(dp));
    		for(int i = 1; i < n; i++) dp[0][i] = 1;
    		for(int i = 0; i < (n - 1) * (n - 1); i++) {
    			for(int j = 0; j < n; j++) {
    				for(int k = 0; k < n; k++) {
    					int d = (k - j) * (k - j);
    					if(!d || i + d > (n - 1) * (n - 1)) continue;
    					dp[i + d][k] += dp[i][j];
    				}
    			}
    		}
    
    		if(m < (n - 1) * (n - 1)) {
    			LL ans = 0;
    			for(int i = 0; i < n; i++) ans += dp[m][i];
    			printf("%u
    ", ans);
    			continue;
    		}
    
    		sz = N;
    		int s = (n - 1) * (n - 1);
    		for(int i = 0; i < (n - 1) * (n - 1); i++)
    			for(int j = 0; j < n; j++)
    				a[i * n + j] = dp[i][j];
    		Matrix M;
    		
    		for(int i = n; i < N; i++) M.a[i - n][i] = 1;
    		for(int i = 0; i < n; i++)
    			for(int j = 0; j < n; j++) if(j != i) {
    				int d = (j - i) * (j - i);
    				M.a[N - n + i][n * (s - d) + j] = 1;
    			}
    		M = pow_mod(M, m - (n - 1) * (n - 1) + 1);
    		LL ans = 0;
    		for(int i = N - n; i < N; i++)
    			for(int j = 0; j < N; j++)
    				ans += M.a[i][j] * a[j];
    		printf("%u
    ", ans);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    nodejs+mongoose操作mongodb副本集实例
    创建mongodb副本集操作实例
    SpringBoot(二)Web整合开发
    SpringBoot(一)走进Springboot的世界
    Git(二)Git几个区的关系与Git和GitHub的关联
    Git(一)之基本操作详解
    HttpClient(二)HttpClient使用Ip代理与处理连接超时
    HttpClient(一)HttpClient抓取网页基本信息
    Jsoup(一)Jsoup详解(官方)
    MongoDB(一)环境搭建与初始配置
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/5256508.html
Copyright © 2011-2022 走看看