快速幂取模

今天acm培训知识:快速幂取模问题

有时我们会碰到求a^b%c的问题,当数据较大时我们有一种比较好的方法(汗,忘了叫什么方法了)


思路:

我们先看命题1:(a*b)%c=(a%c*b%c)%c 括号里面可以有n项乘法。

;首先很容易理解这个,进而有个拓展命题 2:若a>c,则a^b%c=((a%c)^b)%c;



这时我们考虑到二进制,因为a^2%c,可以化为a%c的一些运算,把b化为二进制。


例如:3^11%4.考虑11为1011B(二进制),故而3^11%4=((3^1000B%4) *( 3^10B%4)*(3^1B%4))%3。对于二进制位为1的进行计算.


整体思路就是不断模2除2(化二进制),同时底数不断平方(10011,权值依次为右边一位的平方),同时底数若大于c可以取模(命题2)


这时我们大概可以写出算法.

int powermod(int a,int b,int c)
{
	int ans=1;
	while(b)
	{
		if(b&1)		//b是奇数,即二进制最后一位为1
		   ans*=(ans*a)%c;
		a=(a*a)%c;      //权值不断开方,同时可以模c无影响
		b=b>>1;		//不断右移除2
	}
	return ans;
}

附:HDU1061


#include<stdio.h>
#include<math.h>
int fun(int a,int b,int c)
{
	a%=c;
	int ans=1;
	while(b)
	{
		if(b&1)
		{
			ans*=a;
			ans%=c; 
		}
		a=a*a%c;	
		b=b>>1;
	}
	return ans;
}
int main()
{
	int n,ncase;
	scanf("%d",&ncase);
	while(ncase--)
	{
		scanf("%d" ,&n);
		printf("%d\n",fun(n,n,10));
	}
	return 0;
}


当然除了整数的快速幂取模,还有矩阵的翻版.类似的换为矩阵的乘法和取模,(矩阵的取模指的是每个元素取模)


附:HDU1575 


 #include<stdio.h>
#include<string.h>
#define c 9973
#define MAX 11
int n,k,ans[MAX][MAX],a[MAX][MAX];
void matrixmulmod(int x[MAX][MAX],int y[MAX][MAX])
{
	int temp[MAX][MAX]={0};
	int i,j,k;
	for(i=0;i<n;++i)
		for(j=0;j<n;++j)
		{
			for(k=0;k<n;++k)
				temp[i][j]+=x[i][k]*y[k][j];
			temp[i][j]%=c;
		}
	for(i=0;i<n;++i)
		for(j=0;j<n;++j)
			x[i][j]=temp[i][j];
}
void fun()
{
	memset(ans,0,sizeof(ans));  //注意还得初始化,多次运算
	for(int i=0;i<n;++i)
		ans[i][i]=1;
	while(k)
	{
		if(k&1)
		{
			matrixmulmod(ans,a);
		}
		matrixmulmod(a,a);
		k=k>>1;
	}
}
int main()
{
	int i,j,ncase,sum;
	scanf("%d",&ncase);
	while(ncase--)
	{
		scanf("%d%d",&n,&k);
		for(i=0;i<n;++i)
			for(j=0;j<n;++j)
				scanf("%d",&a[i][j]);
		fun();
		sum=0;

		for(i=0;i<n;++i)
			sum+=ans[i][i];
		printf("%d\n",sum%c);
	}
	return 0;
}
//即矩阵快速幂取模

//思路:快速幂取模注意细节,初始化等等细节问题


好了,今天的一半学习内容到此,快速幂取模。还是很弱的我,一天做了4,5题,好多思路都在他人的指导下纠结写完,还得继续努力啊.


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值