hdu5187_zhx's contest(快速幂+快速乘法)

还是第一次用快速乘法呢,以前知道快速幂的道理,做BC的时候用同样的道理以加法改了一下乘法,后来一查原来有叫“快速乘法”的。

 

Problem Description

As one of the most powerful brushes, zhx is required to give his juniors n problems.
zhx thinks the ith problem's difficulty is i. He wants to arrange these problems in a beautiful way.
zhx defines a sequence {ai} beautiful if there is an i that matches two rules below:
1: a1..ai are monotone decreasing or monotone increasing.
2: ai..an are monotone decreasing or monotone increasing.
He wants you to tell him that how many permutations of problems are there if the sequence of the problems' difficulty is beautiful.
zhx knows that the answer may be very huge, and you only need to tell him the answer module p.

 Input

Multiply test cases(less than 1000). Seek EOF as the end of the file.
For each case, there are two integers n and p separated by a space in a line. (1≤n,p≤1018)

 Output

For each test case, output a single line indicating the answer.
 Sample Input

2 233 3 5

 Sample Output

2 1

 

题目的意思是秋满足这两个条件

1: a1~ai are monotone decreasing or monotone increasing.
2: ai~an are monotone decreasing or monotone increasing.

的序列的数量。

就是以那个ai为分水岭,左边和右边都分别是单调增或单调减如图

hdu5187_zhx's contest(快速幂+快速乘法)_第1张图片

就这四种情况,其中头两种总共就是两个序列,也就是从头到尾递增和从头到尾递减。

后两种方式就是把序列中德数分为左右两派,分完以后左右两边各自内部的排法就已经确定了,至于ai早就确定了(不是全局最大就是全局最小),而除了ai的每一个数都有选择在左或是在右两种选择,所以是2^(n-1),总共就是2^n,而这里包括了前两种的方案,所以要-4,最终应有2^n-2种。

看数据范围就知道要用快速幂,不过可惜如果只用快速幂会错,应为n和p的范围都是10^18,快速幂里在还没有模p之前的乘法都有可能超出long long int。所以想到用加法,a*b就是b个a相加,每一步都模p,然后用快速幂的原理不断二分,这就是所谓的快速乘法。

还有就是特殊数据,当n输入为1的时候情况数不是0而是1,当然不像BC上说的那样结果就是1,而是1MODp

 

代码:

#include 
#include
using namespace std;
long long int n,p,res;

long long modmul(long long a,long long b,long long m)
{
    long long d,t;
    d=0;
    t=a;
    while(b>0)
    {
        if(b%2==1)
            d=(d+t)%m;
        b=b/2;
        t=(t+t)%m;
    }
    return d;
}

long long int modexp(long long a,long long b,long long m)
{
    long long d,t;

    d=1;
    t=a;
    while (b>0)
    {
        if (b%2==1)
            d=modmul(d,t,m)%m;
        b/=2;
        t=modmul(t,t,m)%m;
    }

    return d;
}

int main()
{
    while(scanf("%I64d%I64d",&n,&p)!=EOF)
    {
        if(n==1)
        {
            printf("%I64d\n",n%p);
            continue;
        }
        res=(modexp(2,n,p)+p-2)%p;
        printf("%I64d\n",res);
    }
    //cout << "Hello world!" << endl;
    return 0;
}


 

 

 

 

 

 

你可能感兴趣的:(C++语言,acm)