#数论-模运算#POJ 1150、1284、2115

1.POJ 1150 The Last Non-zero Digit #质因数分解+模运算分治#

先贴两份题解:

http://www.hankcs.com/program/algorithm/poj-1150-the-last-non-zero-digit.html

http://www.cppblog.com/abilitytao/archive/2009/10/31/99907.html

下面是自己看完题解(划掉)之后的理解:

题目要求出组合数Anm=n!/(n-m)!(说实话一开始不知道题目中的NPM到底什么意思。。)的最后一个非零位,那么可以来看看n!的最后一个非零位该如何求得。

求n!:

(1)首先,n!的所有10因子都是要去掉的(因为求非零位),那么2和5也要一对一对的去掉;

(2)接下来把数列分成奇数列:1 2 3 4 5 6 7 8 9 10 –> 1 3 5 7 9 | 2 4 6 8 10

        故有f(n )=f(n/2 )+g(n );

        g(n )可以再分为:1 3 5 7 9 11 13 17 19 21 ……和5的奇数倍 5 15 25……

        故设这个数列中末尾为x(x=1,3,7,9)的个数 g(n,x )=n/10+(n%10>=x)+g(n/5,x );

(3)最后再对数列中末尾为2和5的个数进行比较、特判一下即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

//计算n!中质因子(2/5)的出现次数
int get_2_5(int n,int num)
{
    if(n==0) return 0;
    return n/num+get_2_5(n/num,num);
}

//计算奇数数列中末尾为x的数的出现次数
int g(int n,int x)
{
    if(n==0) return 0;
    return n/10+(n%10>=x)+g(n/5,x);
    //数列还能再次分出子问题,故有g(n/5,x)
}

//计算数列中末尾为x的数的出现次数
int getx(int n,int x)
{
    if(n==0) return 0;
    return getx(n/2,x)+g(n,x);
}

int table[4][4]={
    6,2,4,8,//2^n%10的循环节
    1,3,9,7,//3
    1,7,9,3,//7
    1,9,1,9 //9
};

int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        int num2=get_2_5(n,2)-get_2_5(n-m,2);
        int num5=get_2_5(n,5)-get_2_5(n-m,5);
        int num3=getx(n,3)-getx(n-m,3);
        int num7=getx(n,7)-getx(n-m,7);
        int num9=getx(n,9)-getx(n-m,9);

        int res=1;
        if(num2<num5)
        {
            printf("5\n");
            continue;
        }
        else
        {
            if(num2!=num5)
            {//if num2==num5 那么res应该*1
                res*=table[0][(num2-num5)%4];
                res%=10;
            }

            res*=table[1][num3%4];
            res%=10;
            res*=table[2][num7%4];
            res%=10;
            res*=table[3][num9%4];
            res%=10;
        }
        printf("%d\n",res);
    }
}


2.POJ 1284 Primitive Roots #欧拉函数#

有一个关于原根的概念:若p有原根,则它恰有φ(φ( p))个不同的原根。

欧拉函数定义:对于正整数p,<=p且与p互质的正整数(包括1)的个数记作φ( p)。

这道题其实就是求欧拉数。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

int Euler(int n)
{
    int res=n;
    for(int i=2;i*i<=n;i++)
    {
        while(n%i==0)
        {
            n/=i; res-=(res/i);
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
       res-=(res/n);
    return res;
}

int main()
{
    int p;
    while(~scanf("%d",&p))
        printf("%d\n",Euler(p-1));
    return 0;
}


3.POJ 2115 C Looooops #扩展欧几里得#
http://blog.csdn.net/lyy289065406/article/details/6648546

题意:

        对于C,for(i=A ; i!=B ;i +=C),在k位存储系统中循环几次才结束。

若在有限次内结束,则输出循环次数n,否则输出FOREVER)

分析推导就直接看大牛的了,代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;

ll extend_gcd(ll a,ll b,ll &x,ll &y)
{  //return d=gcd(a,n);
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    else
    {
        ll t=extend_gcd(b,a%b,x,y);
        ll xx=x,yy=y;
        x=yy;
        y=xx-(a/b)*yy;
        return t;
    }
}

int main()
{
    ll A,B,C,k,x,y;
    while(~scanf("%I64d %I64d %I64d %I64d",&A,&B,&C,&k))
    {
        if(A==0&&B==0&&C==0&&k==0)  break;
        ll a=C,b=B-A,n=(ll)1<<k; //n=2^k
        ll d=extend_gcd(a,n,x,y);

        if(b%d!=0) //方程无解
            printf("FOREVER\n");
        else
        {
            x=(x*(b/d))%n;  //x为方程ax=b(mod n)的最小解
            x=(x%(n/d)+n/d)%(n/d);  //x为方程ax=b(mod n)的最小整数解
            printf("%I64d\n",x);
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/atmacmer/p/5532021.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值