现在的位置: 首页 > 综合 > 正文

寒假集训作业(8)——数学问题

2013年08月18日 ⁄ 综合 ⁄ 共 2618字 ⁄ 字号 评论关闭

最小公倍数和最大公约数

GCD求法:

int gcd(int a,int b)
{
    int temp;
    if(a<b)/*交换两个数,使大数放在a上*/
    {
        temp=a;a=b;b=temp;
    }
    while(b!=0)/*利用辗除法,直到b为0为止*/
    {
        temp=a%b;
        a=b;
        b=temp;
    }
    return a;
}

也可用递归:

int Gcd(int a, int b)
{
    if(b == 0)
        return a;
    return Gcd(b, a % b);
}

GCD的一些性质;

(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p) % p
(a * b) % p = (a % p * b % p) % p
(a^b) % p = ((a % p)^b) % p 


求a^n%p

long exp_mod(long a,long n,long b)
{
    long t;
    if(n==0) return 1%b;
    if(n==1) return a%b;
    t=exp_mod(a,n/2,b);
    t=t*t%b;
    if(n%2==1) t=t*a%b;
    return t;
}

筛选法求素数:

#define Max 1000000
bool prime[Max];
void IsPrime()
{
     prime[0]=prime[1]=0;prime[2]=1;
     for(int i=3;i<max;i++)
        prime[i]=i%2==0?0:1;
     int t=(int)sqrt(Max*1.0);
     for(int i=3;i<=t;i++)
       if(prime[i])
         for(int j=i*2;j<Max;j+=i)
            prime[j]=0;
}

比赛中题目:

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1181

GCD 与 LCM:

#include <iostream>
using namespace std;
int GCD(int a,int b)
{
    int min, max;
    max=a>b?a:b;
    min=a<b?a:b;
    if(max%min==0)
        return min;
    else
        return GCD(min,max%min);
}
int LCM(int a,int b)
{
    return (a*b)/GCD(a,b);
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        cout<<LCM(a,b)<<" "<<GCD(a,b)<<endl;
    }
}

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1468
筛法求素数:

#include <iostream>
#include <cmath>
#define Max 1000001
using namespace std;

bool prime[Max];
void IsPrime()
{
    prime[0]=prime[1]=0;
    prime[2]=1;
    for(int i=3; i<Max; i++)
        prime[i]=i%2==0?0:1;
    for(int i=3; i<=(int)sqrt(Max*1.0); i+=2)
    {
        if(prime[i])
        {
            for(int j=i*2; j<Max; j+=i)
            {
                prime[j]=0;
            }
        }
    }
}
int main()
{
    int n;
    IsPrime();
    while(cin>>n&&n!=0)
    {
        int count=0;
        for(int i=2;i<=n-1;i++)
        {
            if(prime[i]) count++;
        }
        cout<<count<<endl;
    }
}

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1469
素数和模运算结合:

#include <iostream>
#include <cmath>
using namespace std;
long exp_mod(long a,long n,long b)
{
    long t;
    if(n==0) return 1%b;
    if(n==1) return a%b;
    t=exp_mod(a,n/2,b);
    t=t*t%b;
    if(n%2==1) t=t*a%b;
    return t;
}
int is_prime(int n)
{
    if (n == 2)
        return 1;
    if (n % 2 == 0)
        return 0;
    for (int i = 3; i * i <= n; i++)
        if (n % i == 0)
            return 0;
    return 1;
}
int main()
{
    long a,p;
    while(cin>>p>>a&&a!=0&&p!=0)
    {
        if(!is_prime(p)&&(exp_mod(a,p,p)==a)) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }
}

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1470

鸽巢原理的应用:

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

int main()
{
    int a,b,c,d,e;
    int men_max,men_min;
    while(cin>>a>>b>>c>>d>>e&&(a||b||c||d||e))
    {
        men_max=a-b*c-1;
        men_min=a-d+e;
        if(c<0) men_max=a;
        if(e<=0)men_min=0;
        if(men_min<=men_max) cout<<men_min<<" "<<men_max<<endl;
        else cout<<"-1"<<endl;
    }
}

这个题是鸽巢原理(抽屉原理)的初步应用,应做如下理解:

1.在求最大和最小的过程中,男生人数最多的时候即女生人数最小的时候,男生人数最少的时候即女生人数最大的时候;

2.B、C两个数是一个抽屉,抽屉数是B,女生最少人数即为B*C+1;(此时男生最大,为A-B*C-1)

3.D、E两个数是另一个抽屉,抽屉数是D,男生最少的人数即为E,女生最多为D-E;(此时男生最小,为A-D+E)

4.当女生<0即没有女生的时候,男生最少=最多=总人数;

5.当男生<0即没有男生的时候,男生最少=最多=0;

6.当最少人数小于等于最多人数的时候输出正确的;

7.其余一切情况皆为逻辑错误。


心得体会是,可以取反面情况理解,即:什么情况是不成立的。切忌两方面同时考虑,一会儿就晕了。。

抱歉!评论已关闭.