hdu 5187 阴险的爆掉long long

BestCoder第33场上的第二题,表示虽然推出了公式,即:

对于n = 1时,ans = n % p(因为p可能为1,所以不能直接写ans = 1);

对于n > 1时,ans = 2 ^ n - 2。

具体公式的推法这里引用出题人laekov的原话:
1002 zhx and contest
如果n=1,答案是1,否则答案是2n2。
证明:ai肯定是最小的或者最大的。考虑另外的数,如果它们的位置定了的话,那么整个序列是唯一的。
那么ai是最小或者最大分别有2n1种情况,而整个序列单调增或者单调减的情况被算了2次,所以要减2。
要注意的一点是因为p>231,所以要用快速乘法。用法与快速幂相同。如果直接乘会超过long long范围,从而wa掉。
对,没错,就是因为p是2的31次幂,当直接采用快速幂的话,会超long long。
【于是就都是眼泪了TAT~,总之还是太年轻】
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
inline LL Fast_mult(LL x, LL y, LL p) {
    LL t=0;
    for(; y; y>>=1,x=(x+x)%p)
        if(y&1)t=(t+x)%p;
    return t;
}
inline LL power(LL x, LL y, LL p) {
    LL t=1;
    for(; y; y>>=1,x=Fast_mult(x,x,p)%p)
        if(y&1)t=Fast_mult(t,x,p);
    return t;
}
int main() {
    LL n, p;
    while(~scanf("%I64d%I64d", &n, &p)) {
        if(n == 1) printf("%I64d\n", n % p);
        else printf("%I64d\n",(power(2, n, p) - 2 + p) % p);
    }
    return 0;
}


posted @ 2015-03-17 17:37  gaoxiang36999  阅读(228)  评论(0)    收藏  举报