ZHX’s Contest

题目描述
作为史上最贪玩的宏志狗,chty已经数月没交数学作业了,而他在月考中数学考了146分,完爆了全班同学,保平认为自己遭到了光速打脸,于是他给chty出了n道题,教他做人。
chty认为第i道题的难度就是i,他想让这些题目排列起来很漂亮。
chty认为一个漂亮的序列{an}下列两个条件均需满足。

1:a1..ai是单调递减或者单调递增的。

2:ai..an是单调递减或者单调递增的。

他想你告诉他有多少种排列是漂亮的。因为答案很大,所以只需要输出答案模p之后的值。

数据组数<=1000 1<=n,p<=10^18

输入格式
输入数据若干组

每组数据一行两个整数:n,p

输出格式
每组数据输出排列的方案数模p的结果。


基于题意,ai必然是数列中的最大值or最小值。两种情况是一样的,我们考虑ai是最大值。那么对于剩下的 n-1 个数,都有两种选择,放在 ai 左边或者右边。也就是说这种情况共有 2^( n-1 ) 种排列方式,最小值同理,相加共有 2^n种,但是当整个序列单调递增or递减的两种排列被重复计算了1次,所以总排列方式为 2^n-2。

特别地,n=1时,排列方式=1。

数据这么大,显然要用到快速幂,带取模,还要用到快速乘。这两者也还是《进阶指南》讲的清楚明白,回头单写博客啦88!

#include<bits/stdc++.h>
using namespace std;

long long n,p;

long long mul_(long long a,long long b)
{
    long long ans=0LL;
    for(;b;b>>=1) 
    {
        if(b&1) ans=(ans+a)%p;
        a=(a<<1)%p;
    }
    return ans;
}

long long fast_power(long long a,long long b)
{
    long long ans=1LL;
    for(;b;b>>=1) 
    {
        if(b&1) ans=mul_(ans,a);
        a=mul_(a,a);
    }
    return ans;
}

int main()
{
    while(cin>>n>>p)
    {
        if(n==1) printf("1\n");
        else printf("%lld\n",(fast_power(2LL,n)-2+p)%p);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hfl030/article/details/79950146