今天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题,好多思路都在他人的指导下纠结写完,还得继续努力啊.