美文网首页
数学专题整理

数学专题整理

作者: 染微言 | 来源:发表于2017-04-15 11:37 被阅读19次

    数学专题整理

    学习清单

    快速幂、矩阵、数论(逆元、容斥、素数筛、高斯消元)、FFT

    归纳整理

    GCD与LCM

    • GCD计算方式来自公式gcd(a,b)=gcd(b,a%b)
    int gcd(int a, int b){
        return b>0? b : a%b;
    }
    
    • LCM计算方式来自性质ab=gcd(a,b)*lcm(a,b)
    int lcm(int a, int b){
        return a * b / std::__gcd(a, b);
    }
    
    • 还有一个性质lcm(m*a,m*b)=m*gcd(a,b)

    A - GCD LCM

    UVA - 11388

    题解

    给出两个数的GCD和LCM,求这两个数。
    从这里学到了GCD和LCM的计算方法和性质,归纳在上面。由性质可以得到,如果存在的话那么L肯定能够被G整除,既然能够整除那么这两个数就可以是G和L

    代码

    #include <stdio.h>
    int main(){
        int t, g, l;
        scanf(“%d”, &t);
        while (t--){
            scanf("%d%d", &g, &l);
            if (l%g) printf("-1\n");
            else printf("%d %d\n", g, l);
        }
        return 0;
    }
    

    B - Benefit

    UVA - 11889

    题意

    给出A和C两个数,求一个B,使LCM(A,B)=C
    一开始觉得只要B=C/A就行,但是会有问题,比如说A=12,B=16,C=48这个情况,如果只简单地除一下,结果是受到了A的影响的。需要在叠加上它们的最大公约数就可以了。

    代码

    #include <stdio.h>
    #include <algorithm>
    
    int main(){
        int t, a, c, b, g;
        scanf("%d", &t);
        while (t--){
            scanf("%d%d", &a, &c);
            if (c%a){
                printf("NO SOLUTION\n");
                continue;
            }
            b = c / a;
            g = std::__gcd(a, b);
            while (g != 1){
                b *= g;
                a /= g;
                g = std::__gcd(a, b);
            }
            printf("%d\n", b);
        }
        return 0;
    }
    

    C - How do you add?

    UVA - 10943

    题意

    DP。
    m拆分成k个整数有多少种拆法。
    因为个数不多所以直接打表。……个数多了也不会做了。
    dp[i][j]=sum(dp[i-1][k]) (0<k<=j)

    代码

    #include <stdio.h>
    #include <string.h>
    
    int main(){
        int a, b, dp[101][101];
        memset(dp, 0, sizeof(dp));
        for (int i = 0; i <= 100; ++i)
            dp[1][i] = 1;
        for (int i = 2; i <= 100; ++i)
            for (int j = 0; j <= 100; ++j)
                for (int k = 0; k <= j; ++k)
                    dp[i][j] = (dp[i][j] + dp[i-1][k]) % 1000000;
        
        while (scanf("%d%d", &a, &b), a+b)
            printf("%d\n", dp[b][a]);
        
        return 0;
    }
    

    B - Discovering Gold

    LightOJ - 1030

    题意

    数学期望。
    你在洞中最深处(位置1),洞内的坐标是[1, n]。你有一颗色子,抛一下,色子上的数字代表你会到达之后的哪一个位置。洞地上有数量不等的黄金,求能得到黄金的期望。
    期望公式:

    d = p[i]+�(p[i]+p[i+1]+p[i+2]+p[i+3]+p[i+4]+p[i+5]+p[i+6])/6
    

    代码

    /******************************
     *File name: LightOJ1030.cpp
     *Author: wzhzzmzzy
     *Created Time: 五  4/14 14:51:32 2017
     *TODO: LightOJ - 1030 概率
    ******************************/
    #include <cstdio>
    int main(){
        int t, cas = 0;
        scanf("%d", &t);
        while (t--){
            int n, m[105], sum[105] = {};
            double dp[105] = {};
            scanf ("%d", &n);
            for (int i = 1; i <= n; ++i){
                scanf("%d", m+i);
                dp[i] = m[i];
                sum[i] = sum[i-1] + m[i];
            }
            for (int i = n-1; i >= 1; --i){
                int len = i < n-5? 6 : n - i;
                for (int j = i+1; j <= i+len; ++j)
                    dp[i] += dp[j] / len;
            }
            printf("Case %d: %lf\n", ++cas, dp[1]);
        }
        return 0;
    }
    

    D - Just another Robbery

    LightOJ - 1079

    题意

    概率、DP。01背包。

    代码

    /******************************
     *File name: LightOJ1079.cpp
     *Author: wzhzzmzzy
     *Created Time: 五  4/14 15:57:03 2017
     *TODO: LightOJ-1079 期望、dp
    ******************************/
    
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    struct bank{
        double p;
        int m;
    }ba[105];
    double dp[102][10005], p;
    int sum, n;
    
    void solve(){
        for (int i = 1; i <= sum; ++i)
            dp[0][i] = (double)-1;
        dp[0][0] = 0;
    
        for (int i = 1; i <= n; ++i)
            for (int j = 0; j <= sum; ++j){
                dp[i][j] = dp[i-1][j];
                if (j - ba[i].m >= 0 && fabs(dp[i-1][j-ba[i].m]+1) > (double)1e-7){
                    if (fabs(dp[i][j]+1)>(double)1e-7)
                        dp[i][j] = min(dp[i][j], dp[i-1][j-ba[i].m] + (1-dp[i-1][j-ba[i].m])*ba[i].p);
                    else
                        dp[i][j] = dp[i-1][j-ba[i].m] + (1-dp[i-1][j-ba[i].m])*ba[i].p;
                }
            }
    }
    
    int main(){
        int t, cas = 0;
        scanf("%d", &t);
        while (t--){
            sum = 0;
            scanf("%lf%d", &p, &n);
            for (int i = 1; i <= n; ++i){
                scanf("%d%lf", &ba[i].m, &ba[i].p);
                sum += ba[i].m;
            }
            solve();
            for (int i = sum; i >= 0; --i){
                if (dp[n][i] >= 0.0 && p - dp[n][i] > (double)1e-7){
                    printf("Case %d: %d\n", ++cas, i);
                    break;
                }
            }
        }
        return 0;
    }
    

    E - Birthday Paradox

    LightOJ - 1104

    题意

    暴力、概率。
    我的做法是暴力解,因为最多只要不到400人就可以满足条件了。直接暴力跑,卡着TLE的时间过了。

    代码

    /******************************
     *File name: LightOJ1104.cpp
     *Author: wzhzzmzzy
     *Created Time: 五  4/14 21:55:53 2017
     *TODO: LightOJ-1104 暴力
    ******************************/
    
    #include <cstdio>
    int main(){
        int t, cas = 0, n;
        scanf("%d", &t);
        while (t--){
            int ans = 0;
            scanf("%d", &n);
            
            for (int i = 2; i < 400; ++i){
                double sp = 1;
                for (int j = 1; j < i; ++j){
                    sp *= n - j;
                    sp /= n;
                }
                if (sp <= 0.5){
                    ans = i;
                    break;
                }
            }
    
            printf("Case %d: %d\n", ++cas, ans-1);
        }
    }
    

    相关文章

      网友评论

          本文标题:数学专题整理

          本文链接:https://www.haomeiwen.com/subject/epynattx.html