cqyz oj | 单峰排列

Description

  一个 1~n 的全排列 A[i] 是单峰的,当且仅当存在某个x使得:

   A[1] < A[2] < ... < A[x] > A[x+1] > ... > A[n]

  例如,对于9的全排列,125798643是单峰排列,123456789也是单峰排列,但356298741就不是。

  试求n的单峰全排列的个数。

Input

  输入一个数n。

Output

  输出n的全排列中单峰排列的个数。由于这个数可能很大,因此你只需要输出它mod 1234567的值。

Sample Input 1 

3

Sample Output 1

4

Hint

n<=2 000 000 000
 
 
 

 
我们构造符合要求的序列的方法是,按照从大到小的顺序把n到1依次往n个空位里填。
因为是“单峰”,所以当前要填的数一定是在之前填好的数的两侧,选择其中一个位置填,否则就会出现多峰。
这样状态就可以出来了:dp[i][j]表示已经填好的数的左侧有i个空位,右侧有j个空位时,单峰排列的个数
方程也出来了:dp[i][j]=dp[i-1][j](当前数填在左边的空位)+dp[i][j-1](当前数填在右边的空位)
边界也出来了:dp[0][j]=1,dp[i][0]=1
答案也出来了:ans = dp[0][n-1]+dp[1][n-2]+……+dp[n-1][0]
 
但是n的范围极大,这样做空间时间都不行。
看到转移方程和n的关系不大,不如来打个表吧:
1,1,1,1,1,1,1,1,1...
1,2,3,4,5,6,7,8,9...
1,3,6,10...
1,4,10...
1,5...
我们要求的答案就是一条副对角线的数之和
再看看这个和:
1=1
1+1=2
1+2+1=4
1+3+3+1=8
...
 
这不是 杨辉三角吗?这样就变成了数学题:求杨辉三角第n行的和。
看到和有没有发现什么规律?没错,答案就是2 n-1
这里n的范围是<=2 000 000 000,这道题到了这里,就变成了一道
 
快速幂!!!
 

重要的是分析过程,之后代码放不放都没什么必要了。因为要取模,不用写高精度。过程中可能会超过int范围,所以算的时候要开long long,这样就可以过了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define mo 1234567
using namespace std;
typedef long long ll;
int qkpow(int a,int p){
    ll r=1,t=a;
    while(p){
        if(p&1) r = (r*t)%mo;
        t=(t*t)%mo;
        p>>=1;
    }
    return (int)r;
}
int main() {
    int p;
    scanf("%d",&p);
    printf("%d",qkpow(2,p-1));
    return 0;
}
View Code

转载于:https://www.cnblogs.com/de-compass/p/11523581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值