题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5187
题意:对1~n的全部排列{a[1],…,a[n]}中,求共有多少种排列满足如下两个条件。存在一个整数i(1≤i≤n)
- a[1],a[2],…,a[i]为单调递增或单调递减
- a[i],a[i+1],…,a[n]为单调递减或单调递增
思路:利用递推来求最后结果。假设x[n]表示n个数时的种数为x[n]种。那么x[n+1]可以由x[n]递推而来。首先,对于n个数来说,条件中的i可以存在于1~n的任何位置。那么将这些位置分为2类。
- i=1 和 i=n
- 1 < i < n
那么若要求x[n+1],则需将n+1这个数填到序列中。
- 对于第一类,n+1有3个位置可以填,因为第一类此时的情况是1~n是单调的一个序列,所以可以填在n的左右,也可以填在1的旁边(非1和2中间)
- 对于第二类,n+1有2个位置可以填,可以填在i的左右。
所以得递推式
x[n+1] = ( x[n] - 2 ) * 2 + 2 * 3 = 2 * x[n] + 2
( x[n+1] + 2 ) = 2 * ( x[n] + 2 )
x[n] = 2^n - 2 ( n > 1 )
利用快速幂求得结果。注意 快速幂中两个数分别取余后相乘仍会暴数据,所以需要用快速乘法。Ex. a * b 可以看作a个b相加,类似快速幂,做快速乘法。
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#include <cstring>
#include <cassert>
using namespace std;
typedef long long ll;
const int maxn=2222;
const int INF=0x7fffffff;
const int mod=1e7+7;
#define LSON l,m,rt<<1
#define RSON m+1,r,rt<<1|1
#define ESP 1e-7
ll n,p;
ll qa(ll a, ll b) {//快速乘法
ll ans=0;
while(b) {
if(b&1)
ans=(ans+a)%p;
a=(a+a)%p;
b>>=1;
}
return ans;
}
ll qm() {//快速幂
ll ans=1,a=2;
while(n) {
if(n&1)
ans=(qa(ans, a))%p;
a=(qa(a, a))%p;
n>>=1;
}
return ans%p;
}
int main() {
while(scanf("%lld%lld", &n, &p)!=EOF) {
if(n==1) printf("%lld\n", n%p);
else {
ll k=qm()-2;
while(k<0) k+=p;
printf("%lld\n", k);
}
}
return 0;
}