四一。 数论 。4.19(gcd 扩展gcd,素数 ,快速幂)

来源:互联网 发布:日本电影知乎 编辑:程序博客网 时间:2024/04/30 14:23

A 青蛙 POJ 1061 扩展gcd

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;long long extgcd(long long a,long long b,long long &x,long long &y){    int d = a;    if(b != 0)    {        d = extgcd(b, a%b, y, x);        y-= (long long)(a/b) * x;    }    else    {        x = 1;        y = 0;    }    //cout<<"   x :"<<x<<" y: "<<y<<" d: "<<d<<" a: "<<a<<" b: "<<b<<endl;    return d;}int main(){    long long n,m,x,y,l,p,q;    cin>>x>>y>>m>>n>>l;    long long c=y-x;                                                                                                                                          ///ax+by = c    long long gcd,temp;    gcd = extgcd(m-n,l,p,q);                                                                                                                              ///gcd 最大公约数    if(c % gcd != 0)                                                                                                                                           ///c不为gcd的倍数则无解        cout<<"Impossible"<<endl;    else    {        //cout<<p<<c<<endl;        p = p*c/gcd;       // cout<<"p: "<<p<<" gcd: "<<gcd<<endl;       if(gcd<0)        gcd = -gcd;        l = l/gcd;                                                                                                                                        /// ax+by = c 求x最小非负时l = b/gcd;求c最小非负时 l = a*b/gcd(最小公倍数)        p =(p%l+l)%l;                                                                                                                                           ///求最小的非负数x        cout<<p<<endl;    }}















B HDU 2098 拆分素数和 打表

#include<iostream>
using namespace std;

int prime[10000]; ///第i个素数
bool is_prime[10005];/// is_prime[i]为true表示i为素数
// 返回n以内素数的个数
int sieve(int n)
{
    int p = 0;
    for(int i = 2; i <= n; i++)
        is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for(int i = 2; i <= n; i++)
    {
        if(is_prime[i])
        {
            prime[p++] = i;
            for(int j = 2*i; j <= n; j += i)
                is_prime[j] = false;
        }
    }
    return p;
}
int opt(int temp)
{
    int n = temp/2,num=0;
    //cout<<n<<endl;
    for(int i=0; prime[i]<n; i++)
    {
        if(is_prime[temp-prime[i]])                                                                                                             /// 枚举 temp减去一个为素数的因子判断余数是否为素数
        {                    
            num++;
            //cout<<prime[i]<<endl;
        }
    }
    return num;
}
int main()
{
    int temp;
    int p =sieve(10000);
    while(cin>>temp)
    {
        if(temp == 0)
            return 0;
        else
        {
            cout<<opt(temp)<<endl;
        }
    }
    return 0;
}










C POJ 1006  周期  扩展gcd


#include<iostream>
#include<cstdio>
using namespace std;
long long extgcd(long long a,long long b,long long &x,long long &y)
{
    long long d = a;
    if(b != 0)
    {
        d = extgcd(b, a%b, y, x);
        y-= (long long)(a/b) * x;
    }
    else
    {
        x = 1;
        y = 0;
    }
    //cout<<"   x :"<<x<<" y: "<<y<<" d: "<<d<<" a: "<<a<<" b: "<<b<<endl;
    return d;
}
int main()
{
    long long p,e,i,d;
    int n=1;
    while(cin>>p>>e>>i>>d)
    {
        if(p == e && e == i && i == d && d == -1)
            return 0;

        else
        {


            long long c = e-p,l;
            long long temp,sum,gcd,x,y;
            gcd = extgcd(23,28,x,y);                                                                                                                ///gcd 最大公约数
            //cout<<x<<y<<endl;
            x = (long long)x*c/gcd
            sum = p + x*23;
            sum = (sum%644 + 644)%644;                                                                                                    /// ax+by = c, 求最小非负c,作为新一方程的常数项
            gcd = extgcd(23*28/gcd,33,x,y);
            c = i - sum;
            x = (long long)x*c/gcd;
            sum = (23*28/gcd*x+sum);
            sum = (sum%21252+21252)%21252;                                                                                           /// 最小非负c
            if(sum <= d)                                                                                                                                   ///  坑: sum必须大于一个周期 否则例一为0,例二为-10
                sum+=21252;
            cout<<"Case "<<n++<<": the next triple peak occurs in "<<sum - d<<" days."<<endl;
        }
    }
    return 0;
}







D POJ 1995 幂和 快速幂

#include<iostream>
using namespace std;
typedef long long ll;
ll mod_pow(ll x, ll n, ll mod)
{
    if(n == 0)
        return 1;
    ll res = mod_pow(x * x % mod, n / 2, mod);                                                                                              ///   递归直到0次方
    if(n & 1)                                                                                                                                                     ///   n二进制与1二进制得数取最后一位(为奇数)【n为奇数要*x】
        res = res * x % mod;
    return res;
}
int main()
{
    int n,mod;
    cin>>n;
    while(n--)
    {
        int m, sum = 0, x, y;
        cin>>mod;
        cin>>m;
        while(m--)
        {
            cin>>x>>y;
            sum = sum + mod_pow(x, y, mod);                                                                                                     /// 多项和取幂等于分别取幂再取幂
        }
        cout << sum % mod << endl;
    }
    return 0;
}





E HDU 2028 最小公倍数 gcd

#include<iostream>
using namespace std;
int gcd(int a, int b)
{
    if( b == 0)
        return a;
    else
        gcd(b, a%b);
}
int lcm(int a, int b)
{
    return (long long)a*b/gcd(a,b);

}
int main()
{
    int n;
    while(cin>>n)
    {
        int x,y;
        cin>>x;
        n = n-1;
        while(n--)
        {
            cin>>y;
            x=lcm(x,y);                                                                            /// 两个两个求lcm
        }
        cout<<x<<endl;
    }
    return 0;
}

0 0