题意简述
有一列长度为nnn的数,每一个数是111~mmm之间的一个数,并且会至少有一对相邻的数相等。求满足这个条件的数列有多少个。
数据
输入
2 3
输出
6
解释
合法的数列为
(1,1,1)(1,1,2)(1,2,2)(2,1,1)(2,2,1)(2,2,2)
(1,1,1)\\
(1,1,2)\\
(1,2,2)\\
(2,1,1)\\
(2,2,1)\\
(2,2,2)\\
(1,1,1)(1,1,2)(1,2,2)(2,1,1)(2,2,1)(2,2,2)
共666种。
思路
正面想。。。要sisisi啊这什么鬼?暴力枚O(mn)O(m^n)O(mn)然后判???显然不珂以这么干。。。预计得分000分(这珂是省选题啊。。。)
这个时候,听数学老师一句劝永远是最优选择。数学老师曰:
正难则反
我们知道,由刚刚的暴力算法珂知,总情况数是mnm^nmn个。然后我们要求的问题的反面就是:所有相邻的一对数都不相等。
这个珂好考虑多了!!!
确定了第一个(mmm种都珂以)后,剩下的只要保持和上一个不一样就珂以了,无论上一个是什么,现在这一个数都有m−1m-1m−1种选择。这样一考虑就是m×(m−1)n−1m\times (m-1)^{n-1}m×(m−1)n−1种。(注意指数是n−1n-1n−1,因为我们特判了第一个有mmm种,就因为这个贡献了一个blingblingblingblingblingbling的WAWAWA。)
然后打快速幂就珂以了,别忘了取膜。
代码:
//代码水的我不想写注释。。。
#include<bits/stdc++.h>
#define int long long
#define mod 100003
using namespace std;
int qpow(int a,int p,int m)
{
a%=m;
int r=1;
while(p)
{
if (p&1) r=r*a%m;
a=a*a%m,p>>=1;
}
return r;
}
int n,m;
main()
{
scanf("%lld%lld",&m,&n);
printf("%lld\n",(qpow(m,n,mod)-m*qpow(m-1,n-1,mod)%mod+mod)%mod);
return 0;
}