hrbust 1864人类希望——kokoⅠ【数学+快速幂】

人类希望——kokoⅠ
Time Limit: 500 MS Memory Limit: 32768 K
Total Submit: 10(8 users) Total Accepted: 4(4 users) Rating:  Special Judge: No
Description

在HUC星域CS星系,无数的战舰碎片静静的漂浮着,诉说着无言的悲壮。。。。。。这注定是人类历史最悲壮的一天,人类最强的舰队AC舰队在与异形的交战中全军覆没。。。。。。现在,异形大军正全速冲向地球,联邦政府打算做最后一搏,用尽人类的所有资源在打造一支究极无敌炒鸡银河舰队,而你,作为人类最强的科学家koko,需要优化战舰的人工智能系统。

#include <stdio.h>

int cases, caseno;

int n, K, MOD;

int A[1001];

int main() {

    scanf("%d", &cases);

    while( cases-- ) {

        scanf("%d %d %d", &n, &K, &MOD);

        int i, i1, i2, i3, ... , iK;

        for( i = 0; i < n; i++ ) scanf("%d", &A[i]);

        int res = 0;

        for( i1 = 0; i1 < n; i1++ ) {

            for( i2 = 0; i2 < n; i2++ ) {

                for( i3 = 0; i3 < n; i3++ ) {

                    ...

                    for( iK = 0; iK < n; iK++ ) {

                        res = ( res + A[i1] + A[i2] + ... + A[iK] ) % MOD;

                    }

                    ...

                }

            }

        }

        printf("Case %d: %d\n", ++caseno, res);

    }

    return 0;

}

你的任务是,编写一段程序,快速计算这段程序的结果,少年,人类的未来在你的肩上啊!


Input

输入以T开头,代表有T组样例

每组样例的第一行有三个数,n(1 ≤ n ≤ 1000), K(1<=K<2^31), MOD(1<=MOD<=35000)

下一行有n个数Ai(Ai保证在32位无符号整数范围内)


Output

对于每组样例输出程序的运行结果

Sample Input

2

3 1 35000

1 2 3

2 3 35000

1 2


Sample Output

Case 1: 6

Case 2: 36


Author
小伙伴们@哈商大


题意:给出一个长度为n的序列P,进行一个操作:对K个序列P每次取出一个数,然后对取出的数求和,重复n^k次操作并求和,最后对总和取模


思路:当n和k都很大的时候,循环次数会变得很大很大,耗时就不用说了,所以需要寻求"捷径"

先对样例2进行分析 n=2 k=3

序列:1 2

根据取出的数我们可以得到2^3(n^k)个序列

1 1 1

1 1 2

1 2 1

1 2 2

2 1 1

2 1 2

2 2 1

2 2 2

这里的总和为36 结果就是36%35000=36

其实多试几组数据,我们不难发现这n^k个序列中的每个数字的出现次数都是相等的(数字相同也可以独立开,如1 1 2里的两个1可以看成是不同的)

那么对于一个序列A1 A2 A3......An(长度为n)组合出的k个序列

每个数字Ai(1<=i<=n)的出现次数为(n^k)*k/n即(n^(k-1))*k

所以这k个序列的数的总和为A1*(n^(k-1))*k+A2*(n^(k-1))*k+A3*(n^(k-1))*k+......+An*(n^(k-1))*k

合并后为(A1+A2+A3+......+An)*(n^(k-1))*k

由于n^k范围过大,我们对其进行快速幂取模即可


#include<cstdio>
int main()
{
    int n,mod,t;
    long long k,a;
    scanf("%d",&t);
    for (int p=1; p<=t; p++)
    {
        scanf("%d%lld%d",&n,&k,&mod);
        int sum=0;
        for (int i=1; i<=n; i++)
        {
            scanf("%lld",&a);
            sum=(sum+a%mod)%mod;
        }
        int ans=1;
        long long tmp=k-1;
        while(tmp>0)
        {
            if (tmp&1)
                ans=(ans*n)%mod;
            tmp>>=1;
            n=((n%mod)*(n%mod))%mod;
        }
        printf("Case %d: %d",p,(sum*ans*(k%mod))%mod);
    }
}


猜你喜欢

转载自blog.csdn.net/qq_38000095/article/details/70649541