您的位置:首页 > 其它

Hdu 4506 小明系列故事——师兄帮帮忙 +Hdu 1420 (蒙哥马利幂模算法)

2013-03-22 18:07 253 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4506

暴力果断超时,于是又从网上和Hdu的群里学了一个算法。

蒙哥马利幂模
思想:

在幂模运算中,通常是用幂模运算转换为乘模运算。有以下两个公式:

1)a*b%n=(a%n)*(b%n)%n

2)(a+b)%n=(a%n+b%n)%n

当我们计算D=C^15%N时,有:

C1=C*C%N=C^2%N

C2=C1*C%N=C^3%N

C3=C2*C2%N=C^6%N

C4=C3*C%N=C^7%N

C5=C4*C4%N=C^14%N

C6=C5*C%N=C^15%N

所以,幂模运算可以转化为乘模运算。继续看,我们会发现,要求D=C^E%N,要知道E何时能整除2,并不需要反复进行减一或者除二的操作,只需要验证E的二进制个位是0还是1就行了。

#include <cstdio>

__int64 data[10005],ans[10005];
__int64 Cal (__int64 s,__int64 index,__int64 mod)
//蒙哥马利幂模算法
//快速幂
//返回值(s^index)%mod
{
	__int64 ans=1;
	s%=mod;
	while (index>=1)
	{
		if ((index&1)==1)   //奇数
			ans=(ans*s)%mod;
		index>>=1;
		s=s*s%mod;
	}
	return ans;
}

int main ()
{
#ifdef ONLINE_JUDGE  
#else  
	freopen("read.txt","r",stdin);    
#endif 
	int T;
	scanf("%d",&T);
	while (T--)
	{
		int t,n,k,i;
		scanf("%d%d%d",&n,&t,&k);
		__int64 temp=Cal(k,t,1000000007);
		int dis=t%n;    //经过t次,后移了多少位 
		for (i=0;i<n;i++)
		{
			scanf("%I64d",&data[i]);
			ans[i]=data[i]*temp%1000000007;
		}
		for (i=n-dis;i<n;i++)
			printf("%I64d ",ans[i]);
		for (i=0;i<n-dis;i++)
			printf(i!=n-dis-1?"%I64d ":"%I64d\n",ans[i]);
	}
	return 0;
}


1420

#include <cstdio>

int main ()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		__int64 a,b,c,k=1;
		scanf("%I64d%I64d%I64d",&a,&b,&c);
		a%=c;
		while (b>=1)
		{
			if ((b&1)==1)   //奇数
				k=(k*a)%c;
			b>>=1;
			a=a*a%c;
		}
		printf("%d\n",k);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: