HZOJ-41:墙壁涂色

 题目描述

给一个环形的墙壁涂颜色,颜色一共有 k 种,墙壁被竖直地划分成 n 个部分,相邻的部分颜色不能相同。请你写程序计算出一共有多少种给墙壁上色的方案?

例如,当 n=5,k=3​时,下面是一种合法的涂色方案

44934979.jpg

而由于墙壁是环形的,所以下面就是一种非法的方案

10258141.jpg


输入

输入两个数字 n,k(1≤n≤103,2≤k≤10)分别代表墙壁数量和颜色种类。

输出

对于每个询问,输出一行整数,合法的墙壁涂色方案数。


样例输入1
5 3
样例输出1
30
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <stack>
#include <deque>
#include <cmath>
#include <algorithm>

using namespace std;
#define MAX_N 1000
#define MAX_K 10

class BigInt : public vector<int> {
public:
	BigInt() { push_back(0);}
	BigInt(int x) {
		push_back(x);
		process_digit();
	}

	BigInt& operator+=(const BigInt& a) {
		for (int i = 0; i < a.size(); i++) {
			if (i < size()) at(i) += a[i];
			else push_back(a[i]);
		}
		process_digit();
		return *this;
	}

private:
	void process_digit() {
		for (int i = 0; i < size(); i++) {
			if (at(i) < 100000) continue;
			if (i + 1 == size()) push_back(0);
			at(i + 1) += at(i) / 100000;
			at(i) %= 100000;
		}
		return;
	}
};

ostream& operator<<(ostream& out, const BigInt &a) {
	out << a[a.size() - 1];
	for (int i = int(a.size()) - 2; i >= 0; i--) {
		/*for (int j = 10000; j > 0; j /= 10) {
			out << a[i] % (j * 10) / j;
		}*/
		printf("%05d", a[i]);
	}
	return out;
}

BigInt f[2][MAX_K + 5][MAX_K + 5];
int main() {
	int n, k;
	cin >> n >> k;
	//f[ws][i][j]代表ws块墙壁,第一块墙壁染第i种颜色,最后一块墙壁染第j种颜色的方法总数
	for (int i = 1; i <= k; i++) f[1][i][i] = 1;
	for (int ws = 2; ws <= n; ws++) {
		for (int i = 1; i <= k; i++) {
			for (int j = 1; j <= k; j++) {
				f[ws % 2][i][j] = 0;
				for (int l = 1; l <= k; l++) {
					if (l == j) continue;
					f[ws % 2][i][j] += f[(ws - 1) % 2][i][l];
				}
			}
		}
	}
	BigInt ans = 0;
	for (int i = 1; i <= k; i++) {
		for (int j = 1; j <= k; j++) {
			if (i == j) continue;
			ans += f[n % 2][i][j];
		}
	}
	cout << ans << endl;
	return 0;
}
#include <iostream>
#include <vector>
using namespace std;

class BigInt : public vector<int> {
public:
	BigInt() { push_back(0); }
	BigInt(int x) {
		push_back(x);
		process_digit();
	}
	BigInt operator*=(int x) {
		for (int i = 0; i < size(); i++) {
			at(i) *= x;
		}
		process_digit();
		return *this;
	}
	BigInt operator*(int x) {
		BigInt ret(*this);
		ret *= x;
		return ret;
	}
	BigInt operator+=(BigInt a) {
		for (int i = 0; i < a.size(); i++) {
			if (i == size()) push_back(a[i]);
			else at(i) += a[i];
		}
		process_digit();
		return *this;
	}
	BigInt operator+(BigInt a) {
		BigInt ret(*this);
		ret += a;
		return ret;
	}
private:
	void process_digit() {
		for (int i = 0; i < size(); i++) {
			if (at(i) < 10) continue;
			if (i + 1 == size()) push_back(0);
			at(i + 1) += at(i) / 10;
			at(i) %= 10;
		}
		return;
	}
};

ostream& operator<<(ostream& out, BigInt a) {
	for (int i = a.size() - 1; i >= 0; i--) {
		out << a[i];
	}
	return out;
}

BigInt f[1005];

int main() {
	int n, k;
	cin >> n >> k;
	f[1] = k;
	f[2] = f[1] * (k - 1);
	f[3] = f[2] * (k - 2);
	for (int i = 4; i <= n; i++) {
		f[i]  = f[i - 1] * (k - 2) + f[i - 2] * (k - 1);
	}
	cout << f[n];
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云儿乱飘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值