OJ P1509

题目描述
输入两个数 a, b,其中 b 极大。计算 a 的 b 次方对 1337 取模的结果。数据保证 a 在 int 范围内,b 小于 100 位。

输入描述
每个样例输入两行分别表示 a 和 b。

输出描述
每个样例输出一行表示:a 的 b 次方对 1337 取模的结果。

样例输入
2
3

样例输出
8


解析:由于题中的幂指数b不可避免的要使用高精度,本题的关键就在于如何简化对底数a的运算,以及寻求一种配合高精度型的指数的计算方法。

数学原理:牛顿二项展开式
对于任意底数a,都可以分成1337的整数倍数与a对1337取模之和,有如下表达式:
(以下公式均使用公式编辑器构建)
在这里插入图片描述
通过观察上式,我们可以得到一条重要性质
即ab对1337取模等价与kb对1337取模

我们不妨将此性质做一个推广
试想ax先乘上by再对1337取模

同样使用二项式,可以得到
在这里插入图片描述
展开式中不含1337n的项只有k1x乘k2y


得出以上性质后,我们不难推出ab对1337取模等价与每次先对1337取模再乘a循环b次(请读者自证)☆⌒(>。≪)


第二步工作,构造出与高精度表示的指数b相性比较好的计算方法

考虑到高精度采用十进制表示,我们不妨以10为梯度进行划分。如下示例:
在这里插入图片描述
使用上文所述性质,有
在这里插入图片描述
将原问题分解为求k的指数的每一位次方对1337取模,这样便与高精度结合起来了ヾ(≧▽≦*)o


C

#include<stdio.h>
#include<string.h>
#define X 1337
#define N 100
int b[N]={0};
void str_to_int(char p[],int q[],int length){
	//倒序转换 
	int i;
	for(i=0;i<length;i++)
		q[length-i-1]=p[i]-'0';
}
int compute(int a,int length,int carry,int end){
	if(length>end)
		return carry;
	//二项展开式,a^b=(1337*n+k)^b
	//				= k^b + b*k^(b-1)*1337n^1 + … 
	int k,t,i;
	k=a%X;
	for(i=1;i<=b[length];i++)
		carry=(carry*k)%X;
	for(t=1,i=1;i<=10;i++)// k 放大到 k^10, 供下个循环使用 
		t=(t*k)%X;
	
	return compute(t,length+1,carry,end);
}

int main()
{
	int a,n;
	char b1[N];
	while(scanf("%d",&a)!=EOF){
		getchar();
		gets(b1);
		str_to_int(b1,b,strlen(b1));
		n=compute(a,0,1,strlen(b1)-1);
		printf("%d\n",n);
	}
	return 0;
}
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值