【递推】【NOIP模拟】彩灯的问题 Lights
来源:互联网 发布:五子棋c语言判断胜负 编辑:程序博客网 时间:2024/05/09 14:29
题目叙述
为了庆祝2009NOIP的举办,X市决定举行一次规模宏大的联欢晚会。设计师Tom被邀请负责晚会的灯光设计。
晚会舞台的正上方有n 盏可以任意变换颜色的彩灯。它们排列成规则的圆形。为了增加舞台的美感,Tom 决定将任意两盏相邻彩灯设计成不同的颜色。因为演出时还要随时变换彩灯的颜色,所以Tom必须设计出多种方案(只要有一盏对应的彩灯颜色不同,就算两种不同的方案)。
于是一个棘手的问题摆在Tom面前:若有m 种颜色,n 个彩灯,那么不同的设计方案有多少种呢?因为当n ,m 较大时,方案数太多,因此他需要你的帮助。
注意:因为每一盏彩灯的位置固定,所以经过旋转或翻转能重合的也算不同的方案。
输入
输入共有一行,两个数:
n ,m ,依次为彩灯的个数与颜色总数。(1≤n≤100,1≤m≤100)
输出
输出仅有一个数为方案总数。
样例输入
3 4
样例输出
24
先给出自己的很麻烦的递推。
首先这道题一看就是递推。
然后要怎么推呢?
简单来说,我们把灯断开拉成一条链,管他第一个灯在哪,就让他随便。
这样的话第一盏灯的颜色有
对于每种情况分别计算,但是其实都是一样的,所以只需要计算其中一种然后
对于其中的一种,举
看第一层。
比如说是A,那么第二层一定不能是A,只可能是BCD。
很显然BCD每个下面都会有一个A的可能。
再向下一层,则每个不是A的下面的
然后推到了第n盏灯。
如果第
如果第
总的来说,是第
推完了最后一层所有情况的个数即为最终解。
写个图:【0base】排版错乱将就看
B C D
A C D | A B D | A B C
BCD ABD ABC| BCD ACD ABC |BCD ACD ABD
……
…… A B C D ……
…… BCD CD BD BC ……
对于前
递推:
对于本分支答案,
最后乘个
推着还好吧,然而这样的话相比较答案来说需要的高精度就有加减乘三种了,代码复杂度增加不少,我这种蒟蒻就高精度懵逼了。
其实本质都差不多,这个递推式还蛮简单的只涉及到上一层的情况。
欢迎进行优化。
貌似可以求通项?】【懒了】
上代码:
#include <cstdio>#include <iostream>#include <cmath>#include <vector>void jin(vector<int> &s){ //统一进位 int j=0; while(j<s.size()-1){ s[j+1]+=s[j]/10; s[j]%=10; j++; } while(s[j]>=10){ s.push_back(s[j]/10); s[j]%=10; j++; }}void print(vector<int> s){ //打印 for(vector<int>::reverse_iterator it=s.rbegin();it<s.rend();it++) printf("%d", *it); printf("\n");}vector<int> highMulti(vector<int> s, int m){ //高精乘 int w=s.size(); int i=0; for(i=0;i<w;i++) s[i]*=m; jin(s); return s;}vector<int> highMinus(vector<int> a, vector<int> b){ //高精减 for(int i=0;i<b.size();i++){ if(a[i]<b[i]){ a[i+1]-=1; a[i]+=10; } a[i]-=b[i]; } return a;}vector<int> highPlus(vector<int> a, vector<int> b){ //高精加 int i=0; for(i=0;i<b.size();i++) a[i]+=b[i]; jin(a); return a;}int main(){ int n, m, k, w; scanf("%d%d", &n, &m); if(n==1&&m==1){ //邪恶的特判 printf("%d\n", 1); return 0; } k=n-1, w=m; //k就是换了个下标不用管 vector<int> wa; //然后把m高精度存进这个wa去 while(w){ wa.push_back(w%10); //倒着存 w/=10; } vector<int> a; //数列a a.push_back(1); vector<int> mi; //m的幂次 mi.push_back(1); for(int i=0;i<k-1;i++){ a=highMinus(mi, a); //a[i]=m^(i-1)-a[i-1] mi=highMulti(mi, m-1); //mi[i]=mi[i-1]*(m-1) } vector<int> res=highMulti(highPlus(highMulti(mi, m-2), a), m); //res=(mi*(m-2)+a)*m; print(res); return 0;}
总的来说还好吧,嗯大概就是这样。
标算
- 设
f(i) 为用m 种颜色给i 盏彩灯着色的方案数,(i=1,2,...n) 。 我们设三盏连续的彩灯依次编号为i−1 ,i ,i+1 。现在分析彩灯i−1 与彩灯i+1 。- 若彩灯
i−1 与彩灯i+1 颜色不同,则去掉彩灯i ,则变成用m 种颜色给n−1 盏彩灯着色的方案数。即f(i−1) 。 因为彩灯i 有m−2 种情况(它与彩灯i−1 ,i+1 颜色不同),所以此时方案数为(m−2)∗f(i−1) 。 - 若彩灯
i−1 与彩灯i+1 颜色相同,则去掉彩灯i ,并把彩灯i−1 ,i+1 合并成彩灯i′ ,则变成用m 种颜色给i−2 盏彩灯着色的方案数。即f(i−2) 。 因为彩灯i 有m−1 种情况(它与彩灯i−1 ,i+1 颜色不同),所以此时方案数为(m−1)∗f(i−2) 。- 综合1、2得出计算
f(n) 的递归方程式:f(n)=(m−2)∗f(n−1)+(m−1)∗f(n−2).
- 综合1、2得出计算
- 若彩灯
- 边界条件: 由上述分析过程可以看出满足递归式的
n 必须大于3 。故必须先求出f(1) 、f(2) 、f(3) 的值。很明显:
f(1)=m,f(2)=m∗(m−1),f(3)=m∗(m−1)∗(m−2). - 此外,因本题方案数增长很快,因此高精度计算也是必不可少的。
- 【递推】【NOIP模拟】彩灯的问题 Lights
- NOIP-贪心,递推,枚举,模拟
- NOIP模拟题 [递推][DP][搜索]
- 【NOIP 模拟题】中位数(规律+递推)
- 【NOIP 模拟题】求和 (打表找规律+递推)
- 【NOIP 模拟题】[T2]one(递推)
- 【NOIP 模拟题】[T1](递推+乱搞)
- NOIP模拟题[递推][并查集][DP]
- NOIP模拟题 [递推][优化][dp][线段树][离散]
- NOIP模拟题 [LIS][建图][递推][容斥]
- 递推(DP) noip 模拟 不等数列
- [NOIP模拟]BOX(推箱子)-BFS
- 问题 B: 彩灯统计
- NOIP模拟题 2016.7.15 [位运算] [搜索] [递推优化] [计算几何]
- 【NOIP模拟赛】 思维+离线+递推 数列(好题)
- 10.22 2017-57级模拟题 二分+并查集+MST+递推+DP+毒瘤noip
- NOIP模拟赛 四校联考 递推 + 分类讨论 + 树上期望
- NOIP 冲刺:常见的递推之第二类斯特林数
- 聊聊Android的缓存(一)
- 数据结构的二叉链表中序遍历
- hdu1061Rightmost Digit
- (转载)Python学习–数据分析路线
- 从程序员到CTO的Java技术路线图
- 【递推】【NOIP模拟】彩灯的问题 Lights
- CodeForces 612D The Union of k-Segments
- 一个关于类数组中如何使用new
- android studio 添加第三方jar
- 软件工程3
- Pinot中的Inverted Index源码分析
- 乌云章华鹏:如何构建高效的安全运维服务平台
- android toast使用总结
- poj 3273 Monthly Expense