zoukankan      html  css  js  c++  java
  • HIT暑期集训 数论进阶

    中国剩余定理,求解符合若干个x%a[i]≡b[i]的式子的答案x,其中a两两互质(模板中求出的最小的非负整数解)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int a[3],b[3]={23,28,33};
    void exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)
        { 
            x=1;y=0; 
            return;
        }
        exgcd(b,a%b,x,y);
        int tmp=x;
        x=y; 
        y=tmp-a/b*y;
    }
    int crt(int n)
    {
        int i,tmp,ans=0,lcm=1,x,y;
        for (i=0;i<n;++i) lcm*=b[i];
        for (i=0;i<n;++i)
        {
            tmp=lcm/b[i];
            exgcd(tmp,b[i],x,y);
            x=(x%b[i]+b[i])%b[i];
            ans=(ans+tmp*x*a[i])%lcm;
        }
        return (ans+lcm)%lcm;
    }
    int main()
    {
        int p,e,i,d;
        int cnt=0,ans;
        while (scanf("%d%d%d%d",&p,&e,&i,&d)!=EOF)
        {
            if (p==-1) break;
            a[0]=p;
            a[1]=e;
            a[2]=i;
            ans=crt(3);
            if (ans<=d) ans+=21252;
            cnt++;
            printf("Case %d: the next triple peak occurs in %d days.
    ",cnt,ans-d);
        } 
        return 0;
    }
    中国剩余定理,模板题 POJ 1006

     扩展中国剩余定理,求解符合若干个x%m[i]≡r[i]的式子的答案x,其中m不一定两两互质(不会证明,我就记个模板。。)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 15
    using namespace std;
    typedef long long ll;
    ll a[maxn],r[maxn];
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if (b==0)
        { 
            x=1;y=0; 
            return a;
        }
        ll gcd=exgcd(b,a%b,x,y);
        ll tmp=x;
        x=y; 
        y=tmp-a/b*y;
        return gcd;
    }
    ll ex_crt(int n,ll lim)
    {
        ll M=a[1],R=r[1],x,y,d;
        for (int i=2;i<=n;i++)
        {
            d=exgcd(M,a[i],x,y);
            if ((R-r[i])%d) return 0;
            x=(R-r[i])/d*x%a[i];
            R-=M*x;
            M=M/d*a[i];
            R%=M;
        }
        ll ans=(R%M+M)%M;
        if (ans==0) return (lim-ans)/M;
        if (ans>lim) return 0;
        return (lim-ans)/M+1;
    }
    int main()
    {
        int n,lim,i,T;
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d%d",&lim,&n);
            for (i=1;i<=n;i++) scanf("%lld",&a[i]);
            for (i=1;i<=n;i++) scanf("%lld",&r[i]);
            printf("%lld
    ",ex_crt(n,lim));
        } 
        return 0;
    }
    扩展中国剩余定理,模板题HDU 1573

    Miller-Rabin参考博客

    B    UVA 11327

    先求出1e6内的欧拉函数,求出它的前缀和,二分查找分母x,然后从0至x枚举直到找到答案。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 1000005
    using namespace std;
    typedef long long ll;
    ll phi[maxn],sum[maxn],ans1,ans2;
    const int lim=1000000;
    int gcd(int x,int y)
    {
        if (y==0) return x;
        return gcd(y,x%y);
    }
    void prework()
    {
        int i,j;
        phi[1]=2;
        for (i=2;i<=lim;i++)
        {
            if (!phi[i]) 
            {
                for (j=i;j<=lim;j+=i)
                {
                    if (!phi[j]) phi[j]=j;
                    phi[j]=phi[j]/i*(i-1);
                 
                }
            }
        }
        for (i=1;i<=lim;i++) sum[i]=sum[i-1]+phi[i];
    }
    void work(ll x)
    {
        int i,l=0,r=lim,mid;
         while (l<=r)
        {
            mid=(l+r)>>1;
            if (sum[mid]<x) l=mid+1;
            else r=mid-1;
        } 
        /*l=lower_bound(sum+1,sum+lim+1,x)-sum;
        //另一种替代二分的方法 */
        x-=sum[l-1];
        for (i=0;i<=l;i++)
        {
            if (gcd(i,l)==1) x--;
            if (x==0)
            {
                ans1=i;ans2=l;
                return;
            }
        }
    }
    int main()
    {
        ll n;
        int i,T;
        prework();
        while (scanf("%lld",&n)!=EOF && n!=0)
        {
            work(n);
            printf("%d/%d
    ",ans1,ans2);
        } 
        return 0;
    }
    View Code

    D    POJ 3904

    E    HDU 2588

    F    HDU 4704

    题意:(我没看懂题目)求N的划分数。

    答案显然为2N-1,由于N很大(10100000),这里要使用费马小定理,即当p是一个素数且与a互质时,ap-1%p≡1,

    于是令N=N%(mod-1),快速幂求2N-1即可(注意考虑求出来的N为0的情况)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mod 1000000007
    #define maxn 100005
    using namespace std;
    typedef long long ll;
    char s[maxn];
    int pow(int x,int k)
    {
        int now=x,re=1;
        while (k)
        {
            if (k&1) re=(1ll*re*now)%mod;
            k>>=1;
            now=(1ll*now*now)%mod;
        }
        return re;
    }
    int main()
    {
        int i,len,x;
        while (scanf("%s",s)!=EOF)
        {
            x=0;
            len=strlen(s);
            for (i=0;i<len;i++)
            {
                x=(1ll*x*10+s[i]-'0')%(mod-1);//费马小定理
            }
            x=(x-1+mod-1)%(mod-1);
            printf("%d
    ",pow(2,x));
        }
        return 0;
    }
    View Code

    G    SPOJ LCMSUM

    H    POJ 1811

    先用Miller_Rabin算法进行素数判断,再用Pollard_rho分解因子。(模板题)
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<time.h>
    #include<map> 
    using namespace std;
    typedef long long ll;
    const int rep=50;
    map<ll,int>mp;
    ll qmul(ll a,ll b,ll mod)
    {
        ll ans=0;
        a=a%mod;
        while (b)
        {
            if (b&1) ans=(ans+a)%mod;
            a=(a+a)%mod;
            b>>=1;
        }
        return ans;
    }
    ll qpow(ll a,ll b,ll mod)
    {
        ll ans=1;
        a=a%mod;
        while (b)
        {
            if (b&1) ans=qmul(ans,a,mod);
            a=qmul(a,a,mod);
            b>>=1;
        }
        return ans;
    }
    int MR(ll n,int repeat)
    {
        if (n==2 || n==3) return 1;
        int i,j,s=0;
        ll d=n-1;
        while (!(d&1))
        {
            s++;
            d>>=1;
        }
        for (i=0;i<repeat;i++)
        {
            ll a=rand()%(n-3)+2;
            ll x=qpow(a,d,n);
            ll y=0;
            for (j=0;j<s;j++)
            {
                y=qmul(x,x,n);
                if (y==1 && x!=1 && x!=n-1) return 0;
                x=y;
            }
            if (y!=1) return 0;
        }
        return 1;    
    }
     
    ll gcd(ll a,ll b)
    {
        if (b==0) return a;
        else return gcd(b,a%b);
    }
    ll Pollard_Rho(ll n, int c)
    {
        ll i=1,k=2,x=rand()%(n-1)+1,y=x;
        while (1)
        {
            i++;
            x=(qmul(x,x,n)+c)%n;
            ll p=gcd((y-x+n)%n,n);
            if (p!=1 && p!=n) return p;
            if (y==x) return n;
            if (i==k)
            {
                y=x;
                k<<=1;
            }    
        }
    }
    void Find(ll n, ll c)
    {
        if (n==1) return;
        if (MR(n,rep))
        {
            mp[n]++;
            return;
        }
        ll p=n;
        while (p>=n) p=Pollard_Rho(p,c--);
        Find(p,c);
        Find(n/p,c);
    }
    int main()
    {
        ll n;
        int i,T;
        srand(time(NULL));
        scanf("%d",&T);
        while (T--)
        {
            scanf("%lld",&n);
            mp.clear();
            if (MR(n,rep)) printf("Prime
    ");
            else 
            {
                Find(n,rand()%(n-1)+1);
                map<ll,int>::iterator it=mp.begin();
                printf("%lld
    ",it->first);
            }
        }
        return 0;
    }
    View Code

    I    CodeForces 1106F

  • 相关阅读:
    -webkit-line-clamp 多行文字溢出...
    整理一些知识碎片...
    localstorage sessionstorage和cookie的区别
    数据结构 --- Set
    Iterator(遍历器)
    ES6数组方法 -- reduce()
    ES6 -- 展开运算符
    Centos7 + Oracel 18c
    Mysql 查询返回大量数据导致内存溢出
    github的安装和使用
  • 原文地址:https://www.cnblogs.com/lsykk/p/13566518.html
Copyright © 2011-2022 走看看