您的位置:首页 > 其它

完全数+莫比乌斯反演hdu 1695+伪随机数 poj2183

2015-02-01 23:13 363 查看
完全数:

 完全数,又称完美数或完备数,是一些特殊的自然数,它所有的真因子(即除了自身以外的约数)之和,恰好等于它本身。

或者可以理解为,如果n是一个正整数,且所有正因子之和等于2n,那么n称为完全数。

完全数有6个重要性质:

性质1 完全数都能写成连续自然数之和;

性质2 每个完全数的全部因数倒数之和都是2,因此每个完全数都是调和数;

性质3 除了6以外的完全数,每个数都可以写成连续奇数的立方和;

性质4 每个完全数都可以表达成2的一些连续正整数次幂之和;

性质5 完全数都是以6或8结尾;

性质6 位数字相加直到变成个位数,这个个位数一定是1.

附表:前12个完美数(目前共发现48个)

个数
完全数
1
6
2
28
3
496
4
8128
5
33550336
6
8,589,869,056
7
137,438,691,328
8
2,305,843,008,139,952,128
9
2,658,455,991,569,831,744,654,692,615,953,842,176
10
191,561,942,608,236,107,294,793,378,084,303,638,130,997,321,548,169,216
11
13,164,036,458,569,648,337,239,753,460,458,722,910,223,472,318,386,943,117,783,728,128
12
14,474,011,154,664,524,427,946,373,126,085,988,481,573,677,491,474,835,889,066,354,349,131,199,152,128
莫比乌斯反演:



算法实现:小技巧:如果某个素因子的幂大于1,则其莫比乌斯函数值就是0,函数break,return 0.

int mobi(int n)
{
int ans=1;
for(int i=2;i*i<=n;i++)
if(n%i==0){
ans*=-1;
int k=0;
do{
k++;
if(k>1) return 0;
n/=i;
}while(n%i==0);
}
if(n>1) ans*=-1;
return ans;
}


hdu 1695 :GCD

解题思路:这道题有2种解法,莫比乌斯反演或容斥定理,前一种算法比较快,这里用莫比乌斯反演解决。

首先由于gcd(x,y)=k满足gcd(x/k,y/k)=1,所以区间可以缩小为[1/k,b/k],[1/k,d/k],问题也转换成为求两区间【1,b】【1,d】互素的对数。

莫比乌斯反演与容斥定理:http://wenku.baidu.com/view/542961fdba0d4a7302763ad5.html

参考代码+部分注释:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int a,b,c,d,k,mu[maxn],prime[maxn];
ll ans,temp;
bool check[maxn];
void swap(int &a,int &b)
{
int temp;temp=a;a=b;b=temp;
return;
}
void Mobius(int n)
{
memset(check,false,sizeof(check));
mu[1]=1;
int cnt=0;
for(int i=2;i<=n;i++){
if(!check[i]){
prime[cnt++]=i;
mu[i]=-1;
}
for(int j=0;jn) break;
check[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
}
int main()
{
//  freopen("input.txt","r",stdin);
Mobius(100000);
int T;cin>>T;
int count=1;
while(T--){
cin>>a>>b>>c>>d>>k;
cout<<"Case "<d) swap(b,d);
b/=k;
d/=k;
ans=temp=0;
for(int i=1;i<=b;i++) ans+=(ll)mu[i]*(b/i)*(d/i);//求出(1,b),(1,d)之间的互质数的对数
for(int i=1;i<=b;i++) temp+=(ll)mu[i]*(b/i)*(b/i);//求出(1,b),(1,b)之间的互质数的对数
cout<


伪随机数:

函数rand()可以生成0~rand_max之间的随机数,是按指定的顺序来产生整数,因此每次执行rand()语句都打印相同的两个值,所以说C语言的随机并不是真正意义上的随机。

函数srand()可以为随机数生成器播散种子,只要种子不同,rand()函数就会产生不同的随机数序列。srand()称为随机数生成器的初始化器。

poj 2183: Bovine Math Geniuses

解题思路:开个标记数组,记录迭代开始的位置,简单题。

参考代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
int flag[maxn];//标记数组
int x;
int main()
{
//freopen("input.txt","r",stdin);
while(cin>>x){
memset(flag,0,sizeof(flag));
int i=0;
while(!flag[x]){
flag[x]=i;
x=x/10%10000;
x=(x*x)%1000000;
i++;
}
cout<
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  完全数