HDU 6333 Problem B. Harvest of Apples 莫队算法

传送门   ----------------链接

HDU 6333 Problem B. Harvest of Apples 莫队算法_第1张图片

题意:求C(n,0)+C(n,1)+C(n,2)+....C(n,m)

注意到题目的n和m都很大,并且有1e5组数据,暴力一定会超时。一开始想的是C(n,0)+C(n,1)+C(n,2)+....C(n,m)能否化简为

一个组合数表达式,在化简过程中发现了如下规律。

{\color{Red} \sum C\left ( n ,m+1\right )=\sum C \left ( n,m \right )+C\left ( n,m+1 \right )}

 

{\color{Red} \sum C\left ( n+1 ,m \right)=2*\sum C \left ( n,m \right )-C\left ( n,m \right )}

 

{\color{Red} \sum C\left ( n ,m-1\right)=\sum C \left ( n,m \right )-C\left ( n ,m\right )}

 

{\color{Red} \sum C\left ( n-1 ,m \right)=(\sum C \left ( n ,m\right )+C\left ( n-1,m \right ) )/2}

 

于是可以将每次询问看作区间,可以利用莫队算法离线处理出所有的询问。

需要注意的是第四个的除2,直接除答案是不对的,应该乘上2的(mod-2)次方

Code:

#include
using namespace std;
#define maxn 100005
#define LL long long
const LL mod = 1000000007;
int block_size, T;
struct  node
{
    int L, R, id;
    bool operator <(const node &b) const
    {
        return (L / block_size == b.L / block_size) ? (R < b.R) : (L / block_size < b.L / block_size);
    }
} query[maxn];
LL ans, inv2;
LL res[maxn], inv[maxn], factorial[maxn];
LL quickPow(LL  a,  LL b)
{
    LL  temp = 1;
    while(b)
        {
            if(b & 1)
                temp = temp * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
    return temp;
}

void Init()
{
    factorial[0] = 1;
    for(int i = 1; i <= maxn; i++)
        factorial[i] = factorial[i - 1] * i % mod;
    inv[maxn] = quickPow(factorial[maxn], mod - 2);
    for(int i = maxn - 1; i >= 0; i--)
        inv[i] = inv[i + 1] * (i + 1) % mod;
    inv2 = inv[2];
}
LL comb(int n, int m)
{
    return factorial[n] * inv[m] % mod * inv[n - m] % mod;
}
inline LL Nplus(int l, int r)
{
    return ans=(2 * ans % mod - comb(r - 1, l) % mod + mod) % mod;
}
inline LL Mplus(int l, int r)
{
    return ans=(ans % mod + comb(r, l) % mod) % mod;
}
inline LL Mdele(int l, int r)
{
    return ans=(ans % mod - comb(r, l + 1) % mod + mod) % mod;
}
inline LL Ndele(int l, int r)
{
    return ans=(ans % mod + comb(r, l) % mod) * inv2 % mod;
}
void solve()
{
    int l = 1, r = 1, i;
    ans = 2;
    for(i = 0; i < T; i++)
        {
            while(r < query[i].R)   Nplus(l, ++r);

            while(l < query[i].L)   Mplus(++l, r);

            while(l > query[i].L)   Mdele(--l, r);

            while(r > query[i].R)   Ndele(l, --r);

            res[query[i].id] = ans;
        }
}
int main()
{
    int  i;
    Init();
    memset(query, 0, sizeof(query));
    scanf("%d", &T);
    for(i = 0; i < T; i++)
        {
            scanf("%d%d", &query[i].R, &query[i].L);
            block_size = max(block_size, query[i].R);
            query[i].id = i;
        }
    block_size = (int) sqrt(block_size * 1.0);
    sort(query, query + T);
    solve();
    for(i = 0; i < T; i++)
        printf("%I64d\n", res[i]);
    return 0;
}

 

你可能感兴趣的:(数论)