您的位置:首页 > 其它

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

2017-04-24 18:42 197 查看
人类希望——kokoⅠ
Time Limit: 500 MSMemory 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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: