给出f(N)= 1 ^ 1 * 2 ^ 2 * 3 ^ 3 ..... N ^ N的函数。我必须计算f(N)/ f(r)* f(N-r)。 我的c代码如下所示,但它适用于小N,如5或6.
#include<stdio.h>
unsigned long long power(long x, long y)
{
unsigned long long temp;
if( y == 0)
return 1;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
int main(){
unsigned long long N,M,Q,r[100001],j;
int t,i;
scanf("%d",&t);
while(t--){
scanf("%llu%llu%llu",&N,&M,&Q);
for(i=0;i<Q;i++)
scanf("%llu",&r[i]);
for(i=0;i<Q;i++){
unsigned long long mult=1;
for(j=2;j<=N;j++){
mult=mult*(power(j,j));
}
unsigned long long mult1=mult;
mult=1;
//unsigned long long ans=mult/((power(r[i],r[i]))*(power((N-r[i]),(N-r[i]))));
for(j=2;j<=r[i];j++)
mult=mult*(power(j,j));
unsigned long long mult2=mult;
mult=1;
for(j=2;j<=N-r[i];j++)
mult=mult*(power(j,j));
unsigned long long mult3=mult;
mult=1;
unsigned long long ans=mult1/(mult2*mult3);
printf("%llu\n",ans%M);
}
}
return 0;
}
假设,f(5)= 1 ^ 1 * 2 ^ 2 * 3 ^ 3 * 4 ^ 4 * 5 ^ 5 = 86400000.if N非常大N <= 10 ^ 5.然后如何存储这样的一个很大的价值。任何人都可以给我一个有效的算法来找到这个值并将其存储在任何array.thanks中。
答案 0 :(得分:1)
对于无符号整数指数,它主要只是重复乘法的简写(例如x^9
为x*x*x*x*x*x*x*x*x
)。
要有效地计算它(减少乘法次数),您可以使用临时计算。例如,对于x*x*x*x*x*x*x*x*x
,您可以计算y = x*x
并执行y*y*y*y*x
;这是5次乘法而不是8次。您还可以y = x*x
然后z = y*y
然后z*z*x
将其降低到4次乘法。
事实证明,二进制文件很棒,并且很容易找到所需的最少乘法次数 - 指数的二进制数字告诉你。
更具体地说,(对于无符号整数指数,忽略溢出),这有效:
result = 1;
temp = x;
while( exponent != 0) {
if( (exponent & 1) != 0) {
result *= temp;
}
exponent >>= 1;
temp *= temp;
}
return result;
当然溢出将是一个问题。对于大数字,您将需要某种可用于乘法的“大整数”代码(其中temp
和result
变量都是“大整数”)。
“大整数”通常只是一个(可变长度)整数数组,其中数组的每个元素表示大基数中的一个数字(例如,对于32位数字,“base 4294967296”)。如果你想自己实现它,我相信你可以找到乘法和除法的算法;如果不这样做,或者是合适的C库。
另一种选择是使用浮点。我建议不要将其用于近似值,因为在处理大数字时会导致精度损失(并且“非常大的数字”仍会出现溢出)。
答案 1 :(得分:0)
你可以尝试:
unsigned long long power(long x, long y)
{
if( 0 == y ) return 1;
if( 1 == y ) return x;
unsigned long long result = x;
for(long i = 2; i < y; i++ )
{
result *= x;
}
return( result );
}
答案 2 :(得分:0)
你有快速指数函数:
unsigned long long fastpow(unsigned long long a, int b)
{
unsigned long long res = 1;
while (b) {
if (b & 1) res *= a;
b >>= 1;
a *= a;
}
return res;
}
它通常用于加密环境,但可以在这里使用。
正如我在评论中所说,你试图写的功能比事实(N)更快,所以你将无法计算出你在问题中放置的范围(10 ^ 5)会得到足够大的数字,以免它们在任何地方都很容易适应。
使用unsigned long long结果,您只能进入:
f(0) -> 1
f(1) -> 1
f(2) -> 4
f(3) -> 108
f(4) -> 27648
f(5) -> 86400000
f(6) -> 4031078400000
f(7) -> 3319766398771200000
f(8) -> overflows in 64 bit.