【NOIP模拟题】【数学归纳法】【递推】【容斥原理】【等比数列求和】2016.11.15 第三题 小L的珍珠挂饰 题解

小L的珍珠挂饰
【题目描述】 小L通过泥萌的帮助,成功解决了牛栏的修建问题。奶牛们觉得主人非常厉害,于是再也不敢偷懒,母牛们奋力挤奶,生娃。子子孙孙无穷匮也!小L于是成为了一代富豪! 但是一直困扰小L的就是单身问题!小L经过长久的寻觅,小L终于找到了一个心仪的漂亮妹子。于是,小L打算在520那天给妹子一个惊喜!(虽然小L很节约,但是对妹子还是很阔绰的!) 小L决定用K种珍珠为妹子做一串举世无双的珍珠垂饰。珍珠垂饰是由珍珠连接而成的,其长度可以认为就是珍珠垂饰上珍珠的个数。小L现在腰缠万贯,每种珍珠他都拥有N颗。根据将珍珠垂饰打开后珍珠不同的排列顺序可以区别不同种类的项链。现在,小L好奇自己可以组成多少种长度为1至N的不同的珍珠垂饰?当然,为显富有,每串珍珠垂饰都要必须由K种珍珠连成。 答案取模1234567891。 这一定难不倒聪明的你吧!如果你能帮小L解决这个问题,也许他会把最后的资产分给你1/4哦! 【输入格式】
输入包含多组数据。第一行是一个整数T,表示测试数据的个数。每组数据占一行,包含两个整数N和K,用一个空格隔开。
【输出格式】
每组数据输出仅一行,包含一个整数,表示项链的种类数。
【样例输入】
2
2 1
3 2
【样例输出】
2 8
【数据范围】
40 % :1<= N<=100000, 0<=K<=30
70 % :1<= N<= 1000000000, 0<=K<=30时限 :1000ms
80%~100% :T <= 10, 1<= N<= 1000000000, 0<=K<=30 时限:50ms.

直接递推(30%)
我们可以找找规律,利用容斥原理我们不难找出nk+Σ(−1)i∗ C(k,i)∗ (k−i)n的规律。但是这样就会GG。故我们试着列出每个n 的长度的式子,然后我们把每个式子的每一项拿出来,便会发现这是等比数列!
等比数列:
ai,表示等比数列中第i 项,q 表示公比
不妨设s=a1+a2+a3…an,
∴qs=a1∗ q+a2∗ q…an∗ q=a2+a3+a4….+an+1
把它们相减:
(q−1)s=an+1−a1
∴s=an+1−a1q−1

附代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define clr(a,x)  memset(x,a,sizeof(x))
#define ll long long
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif

using namespace std;

const int MOD = 1234567891;
ll c[32][32];
int t,n,m,s;
ll fm,an,a1,q,ans;

template <class T> inline void read(T &xx)
{
    xx = 0;
    T flag = 1;
    char ch = (char)getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch == '-') flag = -1;
        ch = (char)getchar();
    }
    while(ch>='0' && ch<='9')
    {
        xx = (xx<<1) + (xx<<3) + ch - '0';
        ch = (char)getchar();
    }
    xx *= flag;
}

ll mo(int x, int y)
{
    long long ans;
    if(y == 1) return x;
    else
    {
        ans = mo(x, y / 2);
        ans = (ans * ans) % MOD;
        if(y%2 != 0) ans = (ans * x) % MOD;
    }
    return ans;
}

void init()
{
    read(t);
    c[0][0] = 1;
    for(int i = 1; i <= 31; i++)
        for(int j = 1; j <= i; j++)
            c[i][j] = c[i-1][j-1] + c[i-1][j];
}

void work()
{
    while(t--)
    {
        read(n); read(m);
        ans = 0; s = 1;
        if(m == 1) ans = n;
        else
            for(int i = m; i >= 1; i--)
            {
                q = i; a1 = q;
                an = mo(q, n);
                if(q == 1)
                {
                    fm = 1;
                    ans = (ans + s * n * c[m+1][m-i+1]) % MOD;
                    s = s * (-1);
                }
                else
                {
                    fm = mo(q - 1, MOD - 2);
                    ans = (((c[m+1][m-i+1] * (((((an * q) % MOD) - a1 + MOD) * fm) % MOD))% MOD) * s + ans) % MOD;
                    s = s * (-1);
                }
            }
        printf(AUTO"\n", (ans + MOD) % MOD);
    }
}

int main()
{
    freopen("pearl.in","r",stdin);
    freopen("pearl.out","w",stdout);
    init();
    work();
    return 0;
}

你可能感兴趣的:(t66)