嘘~ 正在从服务器偷取页面 . . .

UVA10006 Carmichael Numbers


UVA10006 Carmichael Numbers

题目链接:UVA10006 Carmichael Numbers

题意:若 \(\forall x (1<x<n) ,x^n\equiv x \mod n\) ,且 \(n\) 为合数,则称 \(n\)Carmichael Numbers,多组数据判断 \(n\) 是否是这种数

数据范围 \(2<n<65000\)

合数好处理,直接 \(O(\sqrt{n})\) 暴力判断即可

那么 \(x^n\) 怎么处理呢?

如果我们去一个一个乘,时间复杂度 \(O(n^2)\) ,直接TLE

因此,我们要用到快速幂

对于 \(x^k\) ,根据整数的唯一分解定理和常识,\(k\) 可以写成唯一的二进制形式

\(x^k\) 可以被分解为它二进制位上每一个 \(1\) 的幂的乘积

例如: \(x^{(5)_{10}} = x^{(101)_2} = x^{(100)_2} \times x^{(1)_2} = x^{(4)_{10}} \times x^{(1)_{10}}\)

那么我们只需要把 \(k\) 不断右移一位,看它最后一位是否为 \(1\) ,是就乘上对应的数即可

因此我们就可以在 \(O(n\log{n})\)的时间搞定这题了

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define R register
int n;
bool prime(R int x)
{
	if(x<2)return 0;
	for(R int i=2; i*i<=x; i++)
		if(!(x%i))return 0;
	return 1;
}
int qpow(R int a,R int b)
{
	R int ans=1,base=a%n;
	while(b)
	{
		if(b&1)ans=ans*base%n;
		base=base*base%n; // 要取模,不然中间就溢出了
		b>>=1;
	}
	return ans;
}
void proc()
{
	if(prime(n))
	{
		printf("%lld is normal.\n",n);
		return;
	}
	for(R int x=2; x<n; x++)
		if(qpow(x,n)%n!=x)
		{
			printf("%lld is normal.\n",n);
			return;
		}
	printf("The number %lld is a Carmichael number.\n",n);
}
signed main()
{
	while(~scanf("%lld",&n)&&n)
		proc();
	return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录