zoukankan      html  css  js  c++  java
  • 数论小专题总结

    (主要是各基本知识点的例题,查缺补漏,希望以后比赛不要有本来应该掌握的知识点,却不知道的情况)

    1、一元线性同余方程组的一般性解法(拓展gcd、剩余定理)

     1 /*poj2891*解一次线性同余方程组/
     2 /x%a[i]==r[i]*/
     3 /*通解*/
     4 #include<iostream>
     5 #include<string.h>
     6 #include<stdio.h>
     7 #define maxn  10000+5
     8 #define LL long long
     9 using namespace std;
    10 LL r[maxn],m[maxn];
    11 
    12 void Ex_gcd(LL a,LL b,LL &d,LL &x,LL &y){
    13     if (!b){
    14         x=1;y=0;d=a;
    15     }else{
    16         Ex_gcd(b,a%b,d,y,x);
    17         y=y-x*(a/b);
    18     }
    19 }
    20 LL Ex_crt(LL N){
    21     LL M=m[1],R=r[1],x,y,d;
    22     for(int i=2;i<=N;i++){
    23         Ex_gcd(M,m[i],d,x,y);
    24         if ((r[i]-R)%d!=0) return -1;//无解
    25         x=(r[i]-R)/d*x%(m[i]/d);
    26         R=R+x*M;
    27         M=M/d*m[i];
    28         R%=M;
    29     }
    30     if (R<0) R+=M;
    31     return R;
    32 }
    33 int n;
    34 int main(){
    35     while(~scanf("%I64d",&n)){
    36         for(int i=1;i<=n;i++){
    37             scanf("%I64d%I64d",&m[i],&r[i]);
    38         }
    39         LL ans=Ex_crt(n);
    40         printf("%I64d
    ",ans);
    41     }
    42     return 0;
    43 }
    View Code
     1 /*hdu3579解一次线性同余方程组/
     2 /x%a[i]==r[i]*/
     3 /*通解*/
     4 /*注意,题目要求的是最小“正”整数解,如果同余方程组的解为0,则解是A[i]的最小公倍数*/
     5 #include<iostream>
     6 #include<string.h>
     7 #include<algorithm>
     8 #include<stdlib.h>
     9 #include<stdio.h>
    10 #define maxn  100+5
    11 #define typed long long
    12 using namespace std;
    13 typed r[maxn],m[maxn];
    14 
    15 typed gcd(typed a,typed b){
    16     return b==0?a:gcd(b,a%b);
    17 }
    18 void Ex_gcd(typed a,typed b,typed &d,typed &x,typed &y){
    19     if (!b){
    20         x=1;y=0;d=a;
    21     }else{
    22         Ex_gcd(b,a%b,d,y,x);
    23         y=y-x*(a/b);
    24     }
    25 }
    26 typed Ex_crt(typed N){
    27     typed M=m[1],R=r[1],x,y,d;
    28     for(int i=2;i<=N;i++){
    29         Ex_gcd(M,m[i],d,x,y);
    30         if ((r[i]-R)%d!=0) return -1;//无解
    31         x=(r[i]-R)/d*x%(m[i]/d);
    32         R=R+x*M;
    33         M=M/d*m[i];
    34         R%=M;
    35     }
    36     if (R<0) R+=M;
    37     return R;
    38 }
    39 typed n,T;
    40 typed lcm(){
    41     if (n==1) return m[1];
    42     sort(m+1,m+n+1);
    43     typed GCD=gcd(m[2],m[1]);
    44     for(int i=3;i<=n;i++)
    45     GCD=gcd(m[i],GCD);
    46     typed ans=1;
    47     for(int i=1;i<=n;i++) ans=ans*m[i]/GCD;
    48     return ans;
    49 }
    50 int main(){
    51     cin>>T;
    52     for(int cas=1;cas<=T;cas++){
    53         scanf("%I64d",&n);
    54         for(int i=1;i<=n;i++){
    55             scanf("%I64d",&m[i]);
    56         }
    57         for(int i=1;i<=n;i++){
    58             scanf("%I64d",&r[i]);
    59         }
    60         printf("Case %d: ",cas);
    61         typed ans=Ex_crt(n);
    62         if (ans==0) ans=lcm();
    63         printf("%lld
    ",ans);
    64     }
    65     return 0;
    66 }
    View Code

    2、高次同余方程babystep算法

      1 /*HDU - 2815
      2 题意比较有趣,
      3 但化成数学模型,
      4 就是求K^D=N mod P;
      5 K,P,N已知,求D的最小整数解。
      6 有个小坑,N<P 才可
      7 所以就是个解高次同余方程的题目
      8 */
      9 #include<cmath>
     10 #include<iostream>
     11 #include<string.h>
     12 #include<stdio.h>
     13 #define maxn  65535
     14 #define LL long long
     15 using namespace std;
     16 struct hash{
     17     int a,b,next;
     18 }Hash[maxn*2];
     19 int flg[maxn+70];
     20 int top,idx;
     21 void ins(int a,int b){
     22     int k=b&maxn;
     23     if (flg[k]!=idx){
     24         flg[k]=idx;
     25         Hash[k].next=-1;
     26         Hash[k].a=a;
     27         Hash[k].b=b;
     28         return ;
     29     }
     30     while(Hash[k].next!=-1){
     31         if (Hash[k].b==b) return ;
     32         k=Hash[k].next;
     33     }
     34     Hash[k].next=++top;
     35     Hash[top].next=-1;
     36     Hash[top].a=a;
     37     Hash[top].b=b;
     38 }
     39 
     40 int find(int  b){
     41     int k=b&maxn;
     42     if (flg[k]!=idx) return -1;
     43     while(k!=-1){
     44         if (Hash[k].b==b)
     45             return Hash[k].a;
     46         k=Hash[k].next;
     47     }
     48     return -1;
     49 }
     50 int gcd(int a,int b){
     51     return b==0?a:gcd(b,a%b);
     52 }
     53 int ext_gcd(int a,int b,int &x,int &y){
     54     int t,ret;
     55     if (!b) {
     56         x=1,y=0;return a;
     57     }
     58     else{
     59         ret=ext_gcd(b,a%b,x,y);
     60         t=x;x=y;y=t-a/b*y;
     61         return ret;
     62     }
     63 
     64 }
     65 int Inval(int a,int b,int n){
     66     int x,y,e;
     67     ext_gcd(a,n,x,y);
     68     e=(long long) x*b%n;
     69     return e<0?e+n:e;
     70 }
     71 int pow_mod(long long a,int b,int c){
     72     long long ret=1%c;a=a%c;
     73     while(b){
     74         if (b&1)
     75         ret=ret*a%c;
     76         a=a*a%c;
     77         b=b>>1;
     78     }
     79     return ret;
     80 }
     81 int BabyStep(int A,int B,int C){
     82     top=maxn;++idx;
     83     long long buf=1%C,D=buf,K;
     84     int i,d=0,tmp;
     85     for(i=0;i<=100;buf=buf*A%C,i++)
     86         if (buf==B) return i;
     87 
     88     while((tmp=gcd(A,C))!=1){
     89         if (B%tmp) return -1;
     90         ++d;
     91         C=C/tmp;
     92         B=B/tmp;
     93         D=D*A/tmp%C;
     94     }
     95     int M=(int)ceil(sqrt((double)C));
     96     for( buf=1%C,i=0;i<=M;buf=buf*A%C,i++) ins(i,buf);
     97     for( i=0,K=pow_mod((long long)A,M,C);i<=M;D=D*K%C,i++){
     98         tmp=Inval((int)D,B,C);int w;
     99         if (tmp>=0 && (w=find(tmp))!=-1)
    100         return i*M+w+d;
    101     }
    102     return -1;
    103 }
    104 LL K,P,N;
    105 int main(){
    106     while(cin>>K>>P>>N){
    107         if (N>P){
    108             cout<<"Orz,I can’t find D!"<<endl;
    109             continue;
    110         }
    111         N=N%P;
    112         int tmp=BabyStep(K,N,P);//参数是底数,被除数,除数
    113         if (tmp<0)
    114             cout<<"Orz,I can’t find D!"<<endl;
    115         else
    116             printf("%d
    ",tmp);
    117     }
    118     return 0;
    119 }
    View Code
      1 /*Poj 3243
      2 就是求K^X=N mod P;
      3 K,P,N已知,求X的最小整数解
      4 解高次同余方程的题目
      5 */
      6 #include<cmath>
      7 #include<iostream>
      8 #include<string.h>
      9 #include<stdio.h>
     10 #define maxn  65535
     11 #define LL long long
     12 using namespace std;
     13 struct hash{
     14     int a,b,next;
     15 }Hash[maxn*2];
     16 int flg[maxn+70];
     17 int top,idx;
     18 void ins(int a,int b){
     19     int k=b&maxn;
     20     if (flg[k]!=idx){
     21         flg[k]=idx;
     22         Hash[k].next=-1;
     23         Hash[k].a=a;
     24         Hash[k].b=b;
     25         return ;
     26     }
     27     while(Hash[k].next!=-1){
     28         if (Hash[k].b==b) return ;
     29         k=Hash[k].next;
     30     }
     31     Hash[k].next=++top;
     32     Hash[top].next=-1;
     33     Hash[top].a=a;
     34     Hash[top].b=b;
     35 }
     36 
     37 int find(int  b){
     38     int k=b&maxn;
     39     if (flg[k]!=idx) return -1;
     40     while(k!=-1){
     41         if (Hash[k].b==b)
     42             return Hash[k].a;
     43         k=Hash[k].next;
     44     }
     45     return -1;
     46 }
     47 int gcd(int a,int b){
     48     return b==0?a:gcd(b,a%b);
     49 }
     50 int ext_gcd(int a,int b,int &x,int &y){
     51     int t,ret;
     52     if (!b) {
     53         x=1,y=0;return a;
     54     }
     55     else{
     56         ret=ext_gcd(b,a%b,x,y);
     57         t=x;x=y;y=t-a/b*y;
     58         return ret;
     59     }
     60 
     61 }
     62 int Inval(int a,int b,int n){
     63     int x,y,e;
     64     ext_gcd(a,n,x,y);
     65     e=(long long) x*b%n;
     66     return e<0?e+n:e;
     67 }
     68 int pow_mod(long long a,int b,int c){
     69     long long ret=1%c;a=a%c;
     70     while(b){
     71         if (b&1)
     72         ret=ret*a%c;
     73         a=a*a%c;
     74         b=b>>1;
     75     }
     76     return ret;
     77 }
     78 int BabyStep(int A,int B,int C){//A:底数,B:被除数,C除数
     79     top=maxn;++idx;
     80     long long buf=1%C,D=buf,K;
     81     int i,d=0,tmp;
     82     for(i=0;i<=100;buf=buf*A%C,i++)
     83         if (buf==B) return i;
     84 
     85     while((tmp=gcd(A,C))!=1){
     86         if (B%tmp) return -1;
     87         ++d;
     88         C=C/tmp;
     89         B=B/tmp;
     90         D=D*A/tmp%C;
     91     }
     92     int M=(int)ceil(sqrt((double)C));
     93     for( buf=1%C,i=0;i<=M;buf=buf*A%C,i++) ins(i,buf);
     94     for( i=0,K=pow_mod((long long)A,M,C);i<=M;D=D*K%C,i++){
     95         tmp=Inval((int)D,B,C);int w;
     96         if (tmp>=0 && (w=find(tmp))!=-1)
     97         return i*M+w+d;
     98     }
     99     return -1;
    100 }
    101 LL K,P,N;
    102 //K^X=N mod P;
    103 int main(){
    104     while(cin>>K>>P>>N){
    105         if (K==0 && P==0 && N==0) break;
    106         int ans=BabyStep(K,N,P);
    107         if (ans==-1) puts("No Solution");else cout<<ans<<endl;
    108     }
    109     return 0;
    110 }
    View Code

    3、中国剩余定理

     1 /*Poj1006中国剩余定理:
     2 给定n组数对,使得:
     3 A[i]==X(mod M[i])
     4 
     5 剩余定理描述:
     6 设m1,m2,…,mk是两两互素的正整数,则同余
     7 方程组
     8           x=b1 mod m1
     9           x=b2 mod m2
    10 11           x=bk mod mk
    12     有唯一解:x=(b1T1M1+…+bkTkMk  )mod M
    13     其中,M=m1×m2×…mk(即lcm)
    14            Mi=M/mi
    15            Ti=Mi(-1) mod mi 乘法逆元
    16 
    17 
    18 pps:
    19  应用中国剩余定理,可以简化一些复杂的运算。
    20  如计算  47317 mod 713
    21      解:因为713=2331,令x=47317,
    22         则计算x mod 713等价于求解同余方程:
    23             x=47317 mod 23=1317 mod 23
    24             x=47317 mod 31=817 mod 31
    25    即: x=6 mod 23
    26          x=2 mod 31
    27    根据中国剩余定理可得解x=374(mod 713)
    28    因此:47317 mod 713=374(mod 713)
    29 
    30 */
    31 /*对于这道题啊,因为数据量太小,手动计算即可,
    32 M=23*28*33=21252
    33 ans=(b1*924*6+b2*759*19+b3*644*2-d + M)% M;//最小正整数解
    34 */
    35 #include<iostream>
    36 #include<string>
    37 #include<algorithm>
    38 #include<cstdio>
    39 #include<cstring>
    40 #include<cmath>
    41 #include<queue>
    42 #include<map>
    43 #include<stack>
    44 #include<set>
    45 #include<cstdlib>
    46 
    47 using namespace std;
    48 
    49 int d,b1,b2,b3;
    50 int cas=0;
    51 int main(){
    52     while(cin>>b1>>b2>>b3>>d){
    53         if (d==-1 && b1==-1  && b2==-1 && b3==-1) break;
    54         cas++;
    55         int M=23*28*33;
    56         int ans=(b1*924*6+b2*759*19+b3*644*2-d + M)% M;
    57         if (ans==0) ans=M;//正整数解!
    58         printf("Case %d: the next triple peak occurs in %d days.
    ",cas,ans);
    59     }
    60     return 0;
    61 }
    View Code

     4、二元一次不定方程

     1 /*poj2142
     2 解二元一次不定方程
     3 题目描述:给定质量为a和b的砝码,不限天平左右可以放置砝码,称出一个c的质量的物品就可以了
     4 ax+by=d列出数学方程,x和y的正负表示放置的左右,现在要求
     5 |X|+|Y|尽量小,然后是|aX|+|BY|尽量小
     6 
     7 http://116.255.173.144/index.php?c=article&a=read&id=56659
     8 因为欧几里德扩展算法只能求ax + by = gcd(a, b);所以,先求a, b的最大公约数gcd_ab,对于ax + by = d,令a, b, d同除以gcd_ab,然后可求得(a/gcd_ab)x + (b/gcd_ab)y = 1的最小整数解,然后将求得的这组解乘以d/gcd_ab得x0, y0,就是ax + by = d一组解,由数论知识得ax + by = d的所有解为: x = x0 - bt, y = y0 + at(t为参数),那么,要使|x|+|y|最小,可令x = 0求得一组解,再令y = 0求得一组解,两组比较取较小者就好。
     9 
    10 一般方法,拓展欧几里得解出一组特解(x0,y0)
    11 x0=x0*(c/d);
    12 y0=y0*(c/d);
    13 令d=gcd(a,b),a0=a/d,b0=b/d;
    14 则通解是x=x0+a0t,y=y0-b0t(t不所谓正负)
    15 
    16 这道题,一般都是分析函数的单调性了(需要中学数学知识):
    17 假设a0>b0,当|x|+|y|最小时,有-b0<y<b0(可以画出函数图像)
    18 尝试几组解即可
    19 //http://hi.baidu.com/lydrainbowcat/item/07913682130d07dcd1f8cd83
    20 */
    21 #include <iostream>
    22 #include <string.h>
    23 #include <stdio.h>
    24 #include <stdlib.h>
    25 #include <cmath>
    26 #define LL long long
    27 using namespace std;
    28 
    29 LL abs(LL x){
    30     if (x<0) return -x;else return x;
    31 }
    32 void Ex_gcd(LL a,LL b,LL &x,LL &y,LL &d){//d==gcd(a,b)
    33     if (b==0) {
    34         d=a;x=1;y=0;
    35     }else{
    36         Ex_gcd(b,a%b,y,x,d);y-=x*(a/b);
    37     }
    38 }
    39 int main(){
    40     LL a,b,c,d,x0,y0;
    41     while(cin>>a>>b>>c){
    42         if (a==0 && b==0 && c==0) break;
    43         LL chan=0;
    44         if (a<b){
    45             chan=1;
    46             swap(a,b);
    47         }
    48         Ex_gcd(a,b,x0,y0,d);
    49         x0=x0*c/d;
    50         y0=y0*c/d;
    51         //令y0-b0t==0解出一个特解t0,然后在t0周围测试
    52         LL t0=(y0)*d/a;
    53         LL a0=a/d,b0=b/d;
    54         LL max_xy=999999999;
    55         LL ansx,ansy;
    56         LL max_xayb;
    57         for(LL t=t0-10;t<=t0+10;t++){
    58             LL nx=x0+b0*t;
    59             LL ny=y0-a0*t;
    60             if(max_xy>abs(nx)+abs(ny)){
    61                 max_xy=abs(nx)+abs(ny);
    62                 max_xayb=abs(nx*a)+abs(ny*b);//开始时忘记更新
    63                 ansx=nx;ansy=ny;
    64             }
    65              else if (max_xy==abs(nx)+abs(ny)){
    66                 if (max_xayb>abs(nx*a)+abs(ny*b)){
    67                     max_xayb=abs(nx*a)+abs(ny*b);
    68                     ansx=nx;ansy=ny;
    69                 }
    70             }
    71         }
    72         if (chan) swap(ansx,ansy);
    73         cout<<abs(ansx)<<" "<<abs(ansy)<<endl;
    74     }
    75     return 0;
    76 }
    View Code

    5、n元一次不定方程

     1 /*poj1091跳蚤
     2 很经典的一道题,隐藏在活泼的外表下的是,n元一次不定方程。= =
     3 还有,代数系统,容斥原理的应用 = =!
     4 
     5 题目描述:
     6 1、有一只跳蚤在一个横坐标上跳着,它有1+N张卡片,从大到小,最后一张上是M。每次可选择一张,按照上面的数字,卡片可以重复使用,随便向左还是向右跳。
     7 2、它的目标是跳到左边一个单位的位置
     8 
     9 分析:
    10 1、数学方程:设每张卡片的值是a1,a2.....an,M (1+n张)
    11 假设相应选择了xi次(正负代表左右)
    12 则 a1x1+a2x2+a3x3.....anxn+Mx(n+1)=1
    13 这个方程有解的充要条件是gcd(a1,a2,a3,....,M)==1
    14 2、现在问题转化成了[1,M]的范围内找出几个数(包括M),使它们的gcd等于1,问这种分组有多少?
    15 
    16 容斥原理
    17 1、因为必须包含M这个数,所以一组中的数一定没有公因数(来自M因式分解的因子)
    18 2、容斥:
    19 总排列数M^N-sigm(排除含p1的分组,含p2的....)+sigm(含p1*p2的...含pi*pi+1的)-sigm(p1p2p3.....)....
    20 3、举例:含p1公因子的分组数k=M/p1 是M范围内有因子p1的数的个数.选取其中的N张(有顺序,可重复),总共K^N
    21 4、表示:状态压缩,很久没用了啊
    22 
    23 这个博客不错:http://www.cnblogs.com/zhaoguanqin/archive/2012/02/25/2368058.html
    24 */
    25 #include <iostream>
    26 #include <string.h>
    27 #include <stdio.h>
    28 #include <stdlib.h>
    29 #include <cmath>
    30 #define maxn 3200
    31 #define LL long long
    32 using namespace std;
    33 bool flag[maxn];
    34 LL cnt;
    35 LL prim[maxn];
    36 LL dive[25];
    37 void prim_calc(){//素数打表
    38     cnt=0;
    39     memset(flag,0,sizeof(flag));
    40     for(LL i=2;i<maxn;i++){
    41         if (!flag[i]) {
    42             prim[cnt++]=i;
    43             flag[i]=true;
    44             for(LL j=2*i;j<maxn;j+=i) flag[j]=false;
    45         }
    46     }
    47 }
    48 LL count;
    49 LL divide(LL M){
    50     count = 0;
    51     for(LL i=0;i<cnt;i++){
    52         if (M%prim[i]==0){
    53             dive[count++]=prim[i];
    54             while(M%prim[i]==0) M=M/prim[i];
    55             if (M==1) break;
    56         }
    57     }
    58     if (M>1) dive[count++]=M;
    59 //    for(LL i=0;i<count;i++) cout<<dive[i]<<" ";cout<<endl;
    60     return count;
    61 }
    62 LL N,M;
    63 int main(){
    64     prim_calc();
    65     while(cin>>N>>M){
    66         LL dig=divide(M);//
    67         LL ans=pow(M,N);
    68         LL tmp,flag,i,j;
    69         for(i=1;i<(LL)(1<<dig);i++)//状态压缩
    70         {
    71             tmp=1,flag=0;
    72             for(j=0;j<dig;j++)
    73                 if(i&((LL)(1<<j)))//判断第几个因子目前被用到
    74                     flag++,tmp*=dive[j];
    75             if(flag&1)//容斥原理,奇加偶减
    76                 ans-=pow(M/tmp,N);
    77             else
    78                 ans+=pow(M/tmp,N);
    79         }
    80         cout<<ans<<endl;
    81     }
    82     return 0;
    83 }
    View Code

     6、二元二次不定方程(佩尔方程)

     1 /*HDU3292
     2 佩尔方程(二元二次方程)
     3 形如X^2-d*Y^2=1(d>1)
     4 如果d为不完全数,则有解:否则,无解。
     5 求解佩尔方程的两种方法
     6 1、暴力法(本题)
     7 2、连分数法(zoj3759:http://www.cnblogs.com/little-w/p/3588285.html 8 求佩尔方程的解(矩阵快速幂)
     9 |x[k]|=|x1 d*y1|^(k-1) |x1|
    10 |y[k]|=|y1 x1  |       |y1|
    11 思路:暴力或者连分数法求x1+矩阵快速幂
    12 */
    13 #include <iostream>
    14 #include <string.h>
    15 #include <stdio.h>
    16 #include <cmath>
    17 #define LL long long
    18 #define mod 8191
    19 using namespace std;
    20 
    21 int x,y,d,k;
    22 bool isquare(){
    23     int sq=sqrt(d+0.0);
    24     if (((int)sq*(int)sq)==d) return true;
    25     else return false;
    26 }
    27 void search(){
    28     y=1;
    29     while(1){
    30         x=(long long)sqrt(d*y*y+1);
    31         if (x*x-d*y*y==1)
    32            break;
    33         y++;
    34     }
    35 }
    36 struct Mat
    37 {
    38     LL mat[3][3];
    39 };
    40 Mat operator*(Mat a,Mat b)
    41 {
    42     Mat c;
    43     memset(c.mat,0,sizeof(c.mat));
    44     for (int i=0;i<2;i++)
    45         for (int j=0;j<2;j++)
    46             for (int k=0;k<2;k++)
    47                 if (a.mat[i][k] && b.mat[k][j])
    48                    c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
    49     return c;
    50 }
    51 Mat operator+(Mat a,Mat b)
    52 {
    53     Mat c;
    54     memset(c.mat,0,sizeof(c.mat));
    55     for (int i=0;i<2;i++)
    56         for (int j=0;j<2;j++)
    57             c.mat[i][j]=(a.mat[i][j]+b.mat[i][j])%mod;
    58     return c;
    59 }
    60 Mat E;
    61 void builtE()
    62 {
    63     memset(E.mat,0,sizeof(E.mat));
    64     for (int i=0;i<2;i++)
    65     {
    66         E.mat[i][i]=1;
    67     }
    68 }
    69 Mat operator^(Mat A,int x)
    70 {
    71     Mat c;
    72     builtE();
    73     c=E;
    74     for ( ; x; x>>=1)
    75     {
    76         if ( x & 1)
    77             c = c * A;
    78         A = A * A;
    79     }
    80     return c;
    81 }
    82 int main(){
    83     while(cin>>d>>k){
    84         if (isquare()) {
    85             printf("No answers can meet such conditions
    ");
    86             continue;
    87         }
    88         search();
    89         Mat A;
    90         A.mat[0][0]=x,A.mat[0][1]=d*y,A.mat[1][0]=y,A.mat[1][1]=x;
    91         A=A^(k-1);
    92         Mat B;
    93         B.mat[0][0]=x,B.mat[1][0]=y;
    94         B=A*B;
    95         cout<<B.mat[0][0]<<endl;
    96     }
    97     return 0;
    98 }
    View Code

     7、本原毕达哥拉斯三元组定理

     1 /*fzu1669
     2 毕达哥拉斯三元组的应用
     3 
     4 本原毕达哥拉斯定理:
     5 x=m^2-n^2;
     6 y=2mn;
     7 z=m^2+n^2;
     8 m>n,n奇数m偶数或者n偶数m奇数
     9 注意是本原,即(x,y,z)==1,可通过计算本原加上筛选求得一定范围内的所有(x,y,z)
    10 
    11 题意:
    12 a+b+c<=L,
    13 a,b是直角边,c是斜边
    14 给定L ,求满足上式的三角形的个数
    15 思路:通过上面的定理,枚举出m,n(需满足gcd(n,m)==1),找到本原,筛选可得解
    16 具体实现:假设m>n,则m<sqrt(L),再枚举比m小的n即可,因为L≤2000000,m<1000,单次最多不会超过500000左右
    17 */
    18 #include <iostream>
    19 #include <string.h>
    20 #include <stdio.h>
    21 #include <cmath>
    22 #define LL long long
    23 
    24 using namespace std;
    25 int L;
    26 int gcd(int a,int b){
    27     if (b==0) return a;
    28     else return gcd(b,a%b);
    29 }
    30 int main(){
    31     while(cin>>L){
    32         int up=(int)(sqrt(L+0.0));
    33         int ans=0;
    34         for(int m=1;m<=up;m++){
    35             for(int n=m-1;n>=1;n--){
    36                 if ((m+n)%2==0 || gcd(m,n)!=1) continue;
    37                 int x=m*m-n*n;
    38                 int y=2*n*m;
    39                 int z=m*m+n*n;
    40                 ans+=L/(x+y+z);
    41             }
    42         }
    43         cout<<ans<<endl;
    44     }
    45     return 0;
    46 }
    View Code

    8、欧拉函数的应用 POJ 3696

    {参考:http://blog.csdn.net/xieshimao/article/details/6689780}

    9、lucas定理 HDU3944

  • 相关阅读:
    LeetCode Subsets II
    LeetCode Rotate Image
    LeetCode Palidrome Number
    LeetCode Generate Parentheses
    LeetCode Maximum Subarray
    LeetCode Set Matrix Zeroes
    LeetCode Remove Nth Node From End of List
    Linux Loop设备 使用
    Linux 文件系统大小调整
    LeetCode N-Queens II
  • 原文地址:https://www.cnblogs.com/little-w/p/3606994.html
Copyright © 2011-2022 走看看