• 13级个人结业赛-数学场


    数学场题解。(现学现卖,有缺漏之处,还望包涵。)

    从题目的分布上来看,A,B,C为数论内容,DFI为计算几何,E为矩阵,G题概率。希望你们在本次比赛中有所收获。

    数学A

    对于传统的ax+by=gcd(a,b)使用扩展欧几里得解即可,但是这边题面是ax+by+c=0

    必然存在着差异。当我们求出ax+by=gcd(x,y)题解(x0,y0)的时候,ax+by+c=0的解就是

    ( x0*(-c/gcd(a,b)), y0*(-c/gcd(a,b))); 假如c%gcd(a,b)!=0那么算出来的解就不是整数解了,也就是无解的情况。

    这边给出一个博客供大家学习:http://blog.csdn.net/daniel_ustc/article/details/8273201

     1 #include <iostream>  
     2 #include <stdio.h>  
     3 #include <stdlib.h>  
     4 #include <math.h>  
     5 #include <string.h>  
     6 #include <algorithm>  
     7 using namespace std;  
     8 typedef long long ll;  
     9 const ll maxn=5000000000000000000;  
    10 int is(ll a,ll b)  
    11 {  
    12     if(fabs(a)<=maxn&&fabs(b)<=maxn) return 1;  
    13     return 0;  
    14 }  
    15 ll gcd_ex(ll a,ll b,ll *x,ll *y)  
    16 {  
    17     if(b==0)  
    18     {  
    19         *y=0;  
    20         *x=1;  
    21         return a;  
    22     }  
    23     ll r=gcd_ex(b,a%b,x,y);  
    24     ll t=*x;  
    25     *x=*y;  
    26     *y=t-a/b*(*y);  
    27     return r;  
    28 }  
    29     
    30 int main()  
    31 {  
    32     ll a,b,c,x,y,gcdans;  
    33     while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF)  
    34     {  
    35         gcdans=gcd_ex(a,b,&x,&y);  
    36         if(c%gcdans==0)  
    37         {  
    38             x*=(-c)/gcdans;  
    39             y*=(-c)/gcdans;  
    40         }  
    41         else
    42         {  
    43             printf("%lld %lld
    ",maxn+1,maxn+1);  
    44             continue;  
    45         }  
    46         printf("%lld %lld
    ",x,y);  
    47     }  
    48     return 0;  
    49 }  
    拙计的代码

                              数学B

    求n=a*b*c因子个数。首先对n进行质因数分解。比如n=p1^x1*p2^x2….pk^xk  ,p1,p2,p3…pk为质数。

    那么他的因子就会有(x1+1)*(x2+1)*…*(xk+1)种组合;记得记忆化。不然会超时。

     1 #include <iostream> 
     2 #include <stdio.h> 
     3 #include <stdlib.h> 
     4 #include <math.h> 
     5 #include <string.h> 
     6 #include <algorithm> 
     7 using namespace std; 
     8 typedef long long ll; 
     9 const int maxn=1000005; 
    10 ll a,b,c,num[maxn]= {0},prime[maxn]= {0},status[maxn]= {0}; 
    11 const ll mod=1073741824; 
    12 int workprime() 
    13 { 
    14     int ans=0; 
    15     for(int i=2; i<=maxn; i++) 
    16     { 
    17         if(!status[i]) 
    18         { 
    19             prime[ans++]=i; 
    20             status[i]=1; 
    21             for(int j=i; j<=maxn; j+=i) 
    22                 status[j]=1; 
    23         } 
    24     } 
    25     return ans; 
    26 } 
    27 void count(ll r) 
    28 { 
    29     int ans=r; 
    30     if(!num[r]) 
    31     { 
    32         int b=0; 
    33         num[ans]=1; 
    34         while(r>=prime[b]) 
    35         { 
    36             int cou=0; 
    37             while(r%prime[b]==0) 
    38             { 
    39                 cou+=1; 
    40                 r/=prime[b]; 
    41             } 
    42             b++; 
    43             num[ans]=num[ans]*(cou+1); 
    44             if(r==1) break; 
    45         } 
    46     } 
    47 } 
    48 int main() 
    49 { 
    50     ll sum=0,len; 
    51   
    52     memset(prime,0,sizeof(prime)); 
    53     len=workprime(); 
    54     memset(num,0,sizeof(num)); 
    55     while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF) 
    56     { 
    57         sum=0; 
    58         for(ll i=1; i<=a; i++) 
    59         { 
    60             for(ll j=1; j<=b; j++) 
    61             { 
    62                 for(ll k=1; k<=c; k++) 
    63                 { 
    64                     count(i*j*k); 
    65                     sum=(sum%mod+num[i*j*k])%mod; 
    66                 } 
    67             } 
    68         } 
    69         printf("%lld
    ",sum); 
    70     } 
    71     return 0; 
    72 } 
    View Code

    数学C

    先求出x,y的最简比例。然后求出可以扩大的最大比例k,对应的答案就是k*x,k*y。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <math.h>
     5 #include <string.h>
     6 #include <algorithm>
     7 using namespace std;
     8 int a,b,x,y;
     9 int main()
    10 {
    11     while(scanf("%d%d%d%d",&a,&b,&x,&y)!=EOF)
    12     {
    13         int ans=__gcd(x,y);
    14         x/=ans;
    15         y/=ans;
    16         int k=min(a/x,b/y);///找出允许的最大比例
    17         printf("%d %d
    ",x*k,y*k);///从最终的比例上扩大倍数
    18     }
    19     return 0;
    20 }
    View Code

    数学D

    求出两个矩形的交点。在交点中可能出现4交点,也可能出现8交点。这个就取决于a的大小,当然我们需要求出一个临界角度,旋转之后矩形的对角线刚好和未旋转的矩形对角线重合。求出角度后再求出点,再加个凸包的面积计算就可以了。(听说还可以用”半平面交”然而我不会)

     1 #include <iostream> 
     2 #include <iomanip> 
     3 #include <stdio.h> 
     4 #include <set> 
     5 #include <vector> 
     6 #include <map> 
     7 #include <cmath> 
     8 #include <algorithm> 
     9 #include <memory.h> 
    10 #include <string> 
    11 #include <sstream> 
    12   
    13 using namespace std; 
    14   
    15 const long double pi = 3.1415926535897932384626433832795; 
    16   
    17 long double x[42], y[42]; 
    18 int n; 
    19   
    20 void add(int qx, int qy, long double ang) 
    21 { 
    22     x[n] = cos(ang)*qx-sin(ang)*qy; 
    23     y[n] = sin(ang)*qx+cos(ang)*qy; 
    24     n++; 
    25 } 
    26   
    27 void cut(long double xa, long double ya, long double xb, long double yb) 
    28 { 
    29     long double a = yb-ya, b = xa-xb; 
    30     long double c = -a*xa-b*ya; 
    31     long double eps = (1e-10)*1.00042; 
    32     int nn = 0; 
    33     long double xx[42], yy[42]; 
    34     x[n] = x[0]; 
    35     y[n] = y[0]; 
    36     for (int i=0; i<n; i++) 
    37     { 
    38         long double z1 = a*x[i]+b*y[i]+c; 
    39         if (z1 < eps) 
    40         { 
    41             xx[nn] = x[i]; 
    42             yy[nn] = y[i]; 
    43             nn++; 
    44         } 
    45         long double z2 = a*x[i+1]+b*y[i+1]+c; 
    46         if (z1 < eps && z2 > eps || z1 > eps && z2 < eps) 
    47         { 
    48             long double aa = y[i+1]-y[i], bb = x[i]-x[i+1]; 
    49             long double cc = -aa*x[i]-bb*y[i]; 
    50             long double d = a*bb-b*aa; 
    51             xx[nn] = (b*cc-c*bb)/d; 
    52             yy[nn] = (c*aa-a*cc)/d; 
    53             nn++; 
    54         } 
    55     } 
    56     n = nn; 
    57     for (int i=0; i<n; i++) x[i] = xx[i], y[i] = yy[i]; 
    58 } 
    59   
    60 int main() 
    61 { 
    62     //freopen("in.txt","r",stdin); 
    63     //freopen("out.txt","w",stdout); 
    64     int w, h, iang; 
    65     while(scanf("%d %d %d", &w, &h, &iang)!=EOF) 
    66     { 
    67         long double ang = iang/180.0*pi; 
    68         n = 0; 
    69         add(w, h, ang); 
    70         add(-w, h, ang); 
    71         add(-w, -h, ang); 
    72         add(w, -h, ang); 
    73         cut(w, h, -w, h); 
    74         cut(-w, h, -w, -h); 
    75         cut(-w, -h, w, -h); 
    76         cut(w, -h, w, h); 
    77         x[n] = x[0]; 
    78         y[n] = y[0]; 
    79         long double area = 0; 
    80         for (int i=0; i<n; i++) area += (x[i]-x[i+1])*(y[i]+y[i+1]); 
    81         printf("%f
    ", (double)(0.125*area)); 
    82     } 
    83     return 0; 
    84 } 
    半平面交代码,有兴趣可以看看
      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <math.h>
      5 #include <string.h>
      6 #include <algorithm>
      7 using namespace std;
      8 const double eps=1e-10;
      9 const double pi=acos(-1.0);
     10 double  w,h,a;
     11 struct Point
     12 {
     13     double x,y;
     14     Point(double x=0,double y=0):x(x),y(y) {}///11?¨¬o¡¥¨ºy
     15 };
     16 Point p[10];
     17 typedef Point VC;
     18 ///向量+向量=向量,点+向量=点
     19 VC operator +(VC A,VC B)
     20 {
     21     return VC(A.x+B.x,A.y+B.y);
     22 }
     23 ///点-点=向量
     24 VC operator -(VC A,VC B)
     25 {
     26     return VC(A.x-B.x,A.y-B.y);
     27 }
     28 ///向量*数=向量
     29 VC operator *(VC A,double p)
     30 {
     31     return VC(A.x*p,A.y*p);
     32 }
     33 ///向量/数=向量
     34 VC operator /(VC A,double p)
     35 {
     36     return VC(A.x/p,A.y/p);
     37 }
     38 double Cross(VC A,VC B)
     39 {
     40     return A.x*B.y-A.y*B.x;
     41 }
     42 double Area2(Point A,Point B,Point C)
     43 {
     44     return Cross(B-A,C-A);
     45 }
     46 VC Rotate(VC A,double rad )
     47 {
     48     return VC(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
     49 }
     50 Point GetLineIntersection(Point P,VC v,Point Q,VC w)
     51 {
     52     VC u=P-Q;
     53     double t=Cross(w,u)/Cross(v,w);
     54     return P+v*t;
     55 }
     56 double ConvexPolygonArea(Point *p,int n)
     57 {
     58     double area=0;
     59     for(int i=1; i<n-1; i++)
     60         area+=Cross(p[i]-p[0],p[i+1]-p[0]);
     61     return area/2;
     62 }
     63 int main()
     64 {
     65     //freopen("in.txt","r",stdin);
     66     //freopen("out2.txt","w",stdout);
     67     while(scanf("%lf%lf%lf",&w,&h,&a)!=EOF)
     68     {
     69 
     70         if(h<w) h=w+h,w=h-w,h=h-w;
     71         int len=0;
     72         if(a==0||a==180)
     73         {
     74             printf("%f
    ",w*h);
     75             continue;
     76         }
     77         Point A,AA,B,BB,C,CC,D,DD;
     78         if(a>90) a=180-a;
     79         A=Point(h/2,w/2);
     80         AA=Rotate(A,a*pi/180);
     81         B=Point(-h/2,w/2);
     82         BB=Rotate(B,a*pi/180);
     83         C=Point(-h/2,-w/2);
     84         CC=Rotate(C,a*pi/180);
     85         D=Point(h/2,-w/2);
     86         DD=Rotate(D,a*pi/180);
     87         if(a*1.0-2*(atan(1.0*w/h)*180/pi)>0)
     88         {
     89 
     90             Point p1=GetLineIntersection(A,B-A,DD,CC-DD);
     91             Point p2=GetLineIntersection(A,B-A,AA,BB-AA);
     92             Point p3=GetLineIntersection(D,C-D,DD,CC-DD);
     93              printf("%f
    ",Area2(p1,p2,p3));
     94         }
     95         else if(fabs(a*1.0-2*(atan(1.0*w/h)*180/pi))<eps)
     96         {
     97             printf("%f
    ",w*h);
     98             continue;
     99         }
    100         else
    101         {
    102             p[0]=GetLineIntersection(A,B-A,AA,DD-AA);
    103             p[1]=GetLineIntersection(A,B-A,AA,BB-AA);
    104             p[2]=GetLineIntersection(B,C-B,BB,AA-BB);
    105             p[3]=GetLineIntersection(B,C-B,BB,CC-BB);
    106             p[4]=GetLineIntersection(C,D-C,CC,BB-CC);
    107             p[5]=GetLineIntersection(C,D-C,CC,DD-CC);
    108             p[6]=GetLineIntersection(D,A-D,DD,CC-DD);
    109             p[7]=GetLineIntersection(D,A-D,DD,AA-DD);
    110             printf("%f
    ",ConvexPolygonArea(p,8));
    111         }
    112     }
    113 }
    几何代码

    数学E

    由于n的过大。线性的求法难以忍受。矩阵快速幂+取模(忘记了我就呵呵哒),就可以解决。

    http://www.cnblogs.com/vongang/archive/2012/04/01/2429015.html

     1 #include <iostream> 
     2 #include <stdio.h> 
     3 #include <stdlib.h> 
     4 #include <string.h> 
     5 #include <algorithm> 
     6 using namespace std; 
     7 int aa,bb,n,m,mod[]={1,10,100,1000,10000,100000}; 
     8 struct mxt 
     9 { 
    10     int v[2][2]; 
    11 }ans,temp; 
    12 mxt mul(mxt a,mxt b) 
    13 { 
    14     mxt en; 
    15     memset(en.v,0,sizeof(en.v)); 
    16     for(int i=0;i<2;i++) 
    17         for(int j=0;j<2;j++) 
    18         for(int k=0;k<2;k++) 
    19         en.v[i][j]=(en.v[i][j]+a.v[i][k]*b.v[k][j])%mod[m]; 
    20     return en; 
    21 } 
    22 mxt pow_mod(mxt a,int k) 
    23 { 
    24     mxt r; 
    25     memset(r.v,0,sizeof(r.v)); 
    26     r.v[0][0]=r.v[1][1]=1;
    27     while(k) 
    28     { 
    29         if(k&1) r=mul(r,a); 
    30         a=mul(a,a); 
    31         k>>=1; 
    32     } 
    33     return r; 
    34 } 
    35   
    36 int main() 
    37 { 
    38     int t; 
    39     scanf("%d",&t); 
    40     while(t--) 
    41     { 
    42         scanf("%d%d%d%d",&aa,&bb,&n,&m); 
    43         if(n==0) printf("%d
    ",aa%mod[m]); 
    44         else if(n==1) printf("%d
    ",bb%mod[m]); 
    45         else
    46         { 
    47             memset(temp.v,0,sizeof(temp.v)); 
    48             temp.v[0][0]=aa; 
    49             temp.v[0][1]=bb; 
    50             temp.v[1][0]=aa+bb; 
    51             temp.v[1][1]=bb; 
    52             ans.v[0][0]=ans.v[0][1]=ans.v[1][0]=1;ans.v[1][1]=0; 
    53             ans=pow_mod(ans,n-1); 
    54             printf("%d
    ",(ans.v[0][0]*bb+ans.v[0][1]*aa)%mod[m]); 
    55         } 
    56     } 
    57     return 0; 
    58 } 
    View Code

    数学F

    枚举出四边形的对角线,然后分别在对角线两边(使用叉积判断点在对角线周围的位置)找距离对角线最远的点。要注意对于某一条对角线,如果其他点都在他的一侧的话,就算这个面积再大,也是不能取的

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <math.h>
     5 #include <string.h>
     6 #include <algorithm>
     7 using namespace std;
     8 const int maxn=305;
     9 const double eps=1e-10;
    10 const double pi=acos(-1);
    11 int  n;
    12 struct Point
    13 {
    14     double x,y;
    15     Point(double x=0,double y=0):x(x),y(y) {}///构造函数
    16 };
    17 Point p[maxn];
    18 typedef Point VC;
    19 ///向量+向量=向量,点+向量=点
    20 VC operator +(VC A,VC B){return VC(A.x+B.x,A.y+B.y);}
    21 ///点-点=向量
    22 VC operator -(VC A,VC B) {return VC(A.x-B.x,A.y-B.y);}
    23 ///向量*数=向量
    24 VC operator *(VC A,double p) {return VC(A.x*p,A.y*p);}
    25 ///向量/数=向量
    26 VC operator /(VC A,double p) {return VC(A.x/p,A.y/p);}
    27 double Cross(VC A,VC B){return A.x*B.y-A.y*B.x;}
    28 double Dot(VC A,VC B) {return A.x+B.x+A.y*B.y;}///点积=|A|*|B|*cos<A,B>,A,B的逆时针转旋角,满足交换率
    29 double length(VC A) {return sqrt(Dot(A,A));}///长度
    30 VC Rotate(VC A,double rad)///rad弧度
    31 {
    32     return VC(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
    33 }
    34 Point GetLineIntersection(Point P,VC v,Point Q,VC w)
    35 {
    36     VC u=P-Q;
    37     double t=Cross(w,u)/Cross(v,w);
    38     return P+v*t;
    39 }
    40 double DistanceToLine(Point P,Point A,Point B)///p到直线a,b
    41 {
    42     VC v1=B-A,v2=P-A;
    43     return fabs(Cross(v1,v2))/length(v1);///如不取绝对值,得到的是又向距离。
    44 }
    45 int dcmp(double x)///涉及精度问题
    46 {
    47     if(fabs(x)<eps) return 0;
    48     return x<0?-1:1;
    49 }
    50 bool OnSegment(Point p,Point a1,Point a2)
    51 {
    52     return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
    53 }
    54 VC vv[maxn*maxn];
    55 int main()
    56 {
    57     //freopen("in.txt","r",stdin);
    58     int len=0;
    59     while(scanf("%d",&n)!=EOF)
    60     {
    61         //printf("%d
    ",n);
    62         len=0;
    63         for(int i=0;i<n;i++)
    64         {
    65             scanf("%lf%lf",&p[i].x,&p[i].y);
    66         }
    67         double  ansmax=0;
    68         for(int i=0;i<n;i++)
    69         {
    70             for(int j=i+1;j<n;j++)
    71             {
    72                 //vv[len]=VC(p[j]-p[i]);///向量起点为p[i]
    73                 double ansmax1,ansmax2,anslength=length(p[j]-p[i]);
    74                 //printf("length=%f
    ",anslength);
    75                 ansmax1=ansmax2=0;
    76                 for(int k=0;k<n;k++)
    77                 {
    78                     if(k==i||k==j) continue;
    79                     else
    80                     {
    81                         double ans=Cross(p[j]-p[i],p[k]-p[i]);
    82                         if(ans>0) ansmax1=max(ansmax1,DistanceToLine(p[k],p[i],p[j]));
    83                         else if(ans<0) ansmax2=max(ansmax2,DistanceToLine(p[k],p[i],p[j]));
    84                     }
    85                 }
    86                 if(ansmax1!=0&&ansmax2!=0)
    87                 ansmax=max(ansmax,anslength*(ansmax1+ansmax2)/2);
    88             }
    89         }
    90         printf("%f
    ",ansmax);
    91     }
    92 }
    拙计的代码

    数学G

    裸尼姆博弈,答案在必胜态和必败态里面。

    http://www.cnblogs.com/kuangbin/archive/2011/08/28/2156426.html

     1 #include <iostream> 
     2 #include <stdio.h> 
     3 #include <stdlib.h> 
     4 #include <algorithm> 
     5 using namespace std; 
     6 int main() 
     7 { 
     8     int t; 
     9     scanf("%d",&t); 
    10     while(t--) 
    11     { 
    12         int n; 
    13         scanf("%d",&n); 
    14         int flag=0;
    15         int s=0; 
    16         for(int i=0;i<n;i++) 
    17         { 
    18             int x; 
    19             scanf("%d",&x); 
    20             if(i==0) s=x; 
    21             else s^=x; 
    22             if(x>1) flag=1; 
    23         } 
    24         if(flag==0) 
    25         { 
    26             if(n%2==0) {printf("A
    ");continue;} 
    27             printf("B
    "); 
    28         } 
    29         else
    30         { 
    31             if(s==0) {printf("B
    ");continue;} 
    32             printf("A
    "); 
    33         } 
    34     } 
    35     return 0; 
    36 } 
    View Code

    数学H

    最大值的分布是1,2,….n。分别求出对应的可能数量。比如最大值是k(k>1),那么以k为最大值的数量有k^n-(k-1)^n.然后我们就可以求出概率了。E=概率*k.对E进行化简就会得出E=m-(1/m)^n-(2/m)^n-…-((m-1)/m)^n

     1 #include<stdio.h> 
     2 #include<math.h> 
     3 int main() 
     4 { 
     5     int n,m; 
     6     double sum; 
     7     while(scanf("%d%d",&m,&n)!=EOF) 
     8     { 
     9         sum=m; 
    10         for(int i=1; i<m; i++) 
    11         { 
    12             sum-=pow((double)1.0-(double)i/m,(double)n); 
    13         } 
    14         printf("%.12lf
    ",sum); 
    15     } 
    16     return 0; 
    17 } 
    View Code
  • 相关阅读:
    四校联考【20171001】
    C语言基础知识
    页表和TLB
    python
    Cache组织方式
    On the Spectre and Meltdown Processor Security Vulnerabilities
    latex-组织文本
    深入理解计算机系统
    深入理解计算机系统-计算机系统漫游
    逻辑地址到物理地址的转换
  • 原文地址:https://www.cnblogs.com/linxhsy/p/4550260.html
Copyright © 2020-2023  润新知