人类希望——kokoⅠ | ||||||
| ||||||
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);
}
}