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

博客介绍了完全数的概念及其六个重要性质,并探讨了莫比乌斯反演在解决数学问题中的应用,特别是针对HDU 1695题目。同时,文章还提及了C语言中伪随机数的生成,通过srand()和rand()函数的使用,解释了如何在POJ 2183题目中生成不同的随机数序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

完全数:

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

或者可以理解为,如果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<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值