NC19115 选择颜色

题目

题目描述

n 个人排成一个环形,每个人要从 c 种颜色中选择一个。

牛牛希望相邻的人选择的颜色是不同的

问有多少种方案。

输出方案数对 10007 取模的结果。

人是有顺序的,环旋转同构算不同的方案。

输入描述

输入只有一行,包含用空格分开的两个整数,表示 nc

输出描述

输出一行一个整数,表示答案。

示例1

输入

4 3

输出

18

示例2

输入

1000000000 100

输出

726

说明

10007 取模。

备注

对于所有数据: 3n1000000000,3c100
20 分: c3
40 分: c4
70 分: n10000

题解

知识点:计数dp,运算优化。

fi 为考虑到了第 i 个人,并且第 i 个人与第 1 个人颜色是相同的情况数。

gi 为考虑到了第 i 个人,并且第 i 个人与第 1 个人颜色是不同的情况数。

显然 fi=gi1 ,而 gi=(c1)fi1+(c2)gi1

gi 表达出来,gi=(c1)gi2+(c2)gi1 ,随后解递推:

  1. 二阶线性递推方程的特征方程是 x2=px+q ,即 x2=(c2)x+(c1) ,解得 x=c1 or 1
  2. 于是有 gi=C1(c1)n1+C2(1)n1 ,代入初始条件 g1=0g2=(c1)f1=(c1)c ,得 C1=c1=C2
  3. 因此通项公式是 gi=(c1)i+(c1)(1)i

由于最后一个人肯定不能和第一个相同,因为是环状的,所以答案就是 gn

用快速幂处理即可。

时间复杂度 O(logn)

空间复杂度 O(1)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e4 + 7;
int qpow(int a, int k) {
ll ans = 1;
while (k) {
if (k & 1) ans = a * ans % mod;
k >>= 1;
a = a * a % mod;
}
return ans;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, c;
cin >> n >> c;
cout << (qpow(c - 1, n) + (c - 1) * qpow(-1, n) + mod) % mod << '\n';
return 0;
}
posted @   空白菌  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示