LuoguP3197「HNOI2008」题解

开始补ZR的任务清单/kel

题目描述

监狱有连续编号为 $1 \dots N$ 的 $N$ 个房间,每个房间关押一个犯人,有 $M$ 种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱。

输入格式

输入两个整数 $M,N$

输出格式

可能越狱的状态数,对 $100003$ 取模

Inputs and Outputs examples

Inputs’ e.g. #1

1
2 3

Outputs’ e.g. #1

1
6

分析

这题我记得dls讲的时候是拿来签到的/cy

正难则反,我们考虑用总状态数减去不合法状态数即为答案.

显然总状态数为Tewelvefold way里面的Problem LLA,也就是$m^n$

考虑不合法状态数,即每两个相邻犯人的宗教都不同的方案数.

首先假设$1$号牢房的犯人信仰宗教$A$,这时$A$可以在$[1,m]$里面取值.为了和$1$号牢房犯人的宗教避开,$2$号牢房的犯人信仰的宗教$B$只能有$m-1$种取值.与之类似,为了和$2$号牢房犯人的宗教避开,$3$号牢房的犯人信仰的宗教$C$也只能有$m-1$种取值.

那么依次类推下去,显然可以得到答案:

$$Ans = m^n - m \times (m - 1) ^ {n-1}$$

快速幂即可,注意取模问题

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* Headers */
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<climits>
#include<iostream>
#include<map>
#define FOR(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define ROF(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define FORL(i,a,b,c) for(long long i=(a);i<=(b);i+=(c))
#define ROFL(i,a,b,c) for(long long i=(a);i>=(b);i-=(c))
#define FORR(i,a,b,c) for(register int i=(a);i<=(b);i+=(c))
#define ROFR(i,a,b,c) for(register int i=(a);i>=(b);i-=(c))
#define lowbit(x) x&(-x)
#define LeftChild(x) x<<1
#define RightChild(x) (x<<1)+1
#define RevEdge(x) x^1
#define FILE_IN(x) freopen(x,"r",stdin);
#define FILE_OUT(x) freopen(x,"w",stdout);
#define CLOSE_IN() fclose(stdin);
#define CLOSE_OUT() fclose(stdout);
#define IOS(x) std::ios::sync_with_stdio(x)
#define Dividing() printf("-----------------------------------\n");
namespace FastIO{
const int BUFSIZE = 1 << 20;
char ibuf[BUFSIZE],*is = ibuf,*its = ibuf;
char obuf[BUFSIZE],*os = obuf,*ot = obuf + BUFSIZE;
inline char getch(){
if(is == its)
its = (is = ibuf)+fread(ibuf,1,BUFSIZE,stdin);
return (is == its)?EOF:*is++;
}
inline int getint(){
int res = 0,neg = 0,ch = getch();
while(!(isdigit(ch) || ch == '-') && ch != EOF)
ch = getch();
if(ch == '-'){
neg = 1;ch = getch();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1)+ (ch - '0');
ch = getch();
}
return neg?-res:res;
}
inline void flush(){
fwrite(obuf,1,os-obuf,stdout);
os = obuf;
}
inline void putch(char ch){
*os++ = ch;
if(os == ot) flush();
}
inline void putint(int res){
static char q[10];
if(res==0) putch('0');
else if(res < 0){putch('-');res = -res;}
int top = 0;
while(res){
q[top++] = res % 10 + '0';
res /= 10;
}
while(top--) putch(q[top]);
}
inline void space(bool x){
if(!x) putch('\n');
else putch(' ');
}
}
inline void read(int &x){
int rt = FastIO::getint();
x = rt;
}
inline void print(int x,bool enter){
FastIO::putint(x);
FastIO::flush();
FastIO::space(enter);
}
/* definitions */
#define type_T long long
const int mod = 100003;
type_T m,n;
/* functions */
inline type_T quick_power(type_T a,type_T b,type_T p){
type_T res = 1, base = a;
while(b){
if(b & 1) res = res * base % p;
b >>= 1; base = base * base % p;
}
return res;
}
int main(int argc,char *argv[]){
scanf("%lld%lld",&m,&n);
type_T ans = (quick_power(m,n,mod) - (m % mod) * quick_power(m-1,n - 1,mod) % mod + mod) % mod;
printf("%lld\n",ans);
return 0;
}

THE END