• 牛客暑期多校解题报告: 2


    J

    给定一个数列 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an, 求一个等差数列 a 1 ′ , a 2 ′ , . . . , a n ′ a_1^{'}, a_2^{'},..., a_n^{'} a1,a2,...,an,使得 ∑ i = 1 n ( a i − a i ′ ) 2 \sum_{i=1}^{n}(a_i-a_i^{'})^2 i=1n(aiai)2, 最小,输出这个最小值。
    线性回归,找出一条直线和这组点的竖直距离的平方和最短。
    假设有一堆点 ( x i , y i ) (x_i, y_i) (xi,yi),求一条直线 y ′ = A x + b y^{'}=Ax+b y=Ax+b使得 ∑ i = 1 n ( y i − y ′ ( x i ) ) 2 \sum_{i=1}^{n}(y_i-y^{'}(x_i))^2 i=1n(yiy(xi))2最小
    x ˉ = ( ∑ i = 1 n x i ) / n , y ˉ = ( ∑ i = 1 n y i ) / n \bar{x}=(\sum_{i=1}^{n}x_i)/n, \bar{y}=(\sum_{i=1}^{n}y_i)/n xˉ=(i=1nxi)/n,yˉ=(i=1nyi)/n
    则有
    A = ∑ i = 1 n x i y i − n x ˉ y ˉ ∑ i = 1 n x i 2 − n ( x ˉ ) 2 A=\frac{\sum_{i=1}^{n}x_iy_i - n\bar{x}\bar{y}}{\sum_{i=1}^{n}x_i^2-n(\bar{x})^2}\\ A=i=1nxi2n(xˉ)2i=1nxiyinxˉyˉ
    B = y ˉ − A x ˉ B=\bar{y}-A\bar{x} B=yˉAxˉ
    按照这个结论带入就可以算出答案了。P.S: 线性回归是我在网上找的捏,自己写挂了🫠

    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    const int maxn = 1e5+5;
    int arr[maxn];
    
    namespace GTI
    {
        char gc(void)
           {
            const int S = 1 << 16;
            static char buf[S], *s = buf, *t = buf;
            if (s == t) t = buf + fread(s = buf, 1, S, stdin);
            if (s == t) return EOF;
            return *s++;
        }
        int gti(void)
           {
            int a = 0, b = 1, c = gc();
            for (; !isdigit(c); c = gc()) b ^= (c == '-');
            for (; isdigit(c); c = gc()) a = a * 10 + c - '0';
            return b ? a : -a;
        }
    }
    using GTI::gti;
    
    int main(void)
    {
        /* freopen("in.txt", "r", stdin); */
        int T;
        scanf("%d", &T);
        while(T--) {
            int n = gti();
            long double a, b, b1, mxy, sum_x, sum_y, lxy, xiSubSqr;
            a = b = b1 = mxy = sum_x = sum_y = lxy = xiSubSqr = 0.0;
    
            for(int i = 1; i <= n; ++i) {
                sum_x += i;
                arr[i] = gti();
                sum_y += arr[i];
            }
    
            long double x_avg = sum_x / n;
            long double y_avg = sum_y / n;
    
            for(int i = 1; i <= n; ++i) {
                lxy += (i-x_avg) * (arr[i]-y_avg);
                xiSubSqr += (i-x_avg) * (i-x_avg);
            }
    
            b = lxy/xiSubSqr;
            a = y_avg - b * x_avg;
    
            long double ans = 0;
    
            for(int i = 1; i <= n; ++i) {
                ans += pow(1.0*b*i+a-arr[i], 2);
            }
    
            printf("%.15Lf\n", ans);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    K

    给定一个长度为n的括号序列a,a是另一个长度为m的合法括号序列b的子序列,给定a,求可能的b的数量。
    合法括号序列 A ::= empty | (A) | AB
    dp(i, j, k) 代表b的前i个最多匹配a的前j个,剩下k个左括号未匹配。
    考虑状态转移
    已知状态dp(i, j, k),如果a[j+1]==‘(’, 则向b添加一个’(', 状态转移到dp(i+1, j+1, k+1)其他转移方式同理

    #include 
    #include 
    #include 
    
    using namespace std;
    typedef long long ll;
    const int maxn = 205;
    const int mod = 1e9+7;
    
    ll dp[maxn][maxn][maxn];
    int min(int a, int b) { return a>b?b:a; }
    
    int main(void)
    {
        int T, n, m;
        char s[300];
        scanf("%d", &T);
    
        while(T--) {
            scanf("%d%d", &n, &m);
            scanf(" %s", s);
            for(int i = 1; i <= m; ++i) {
                for(int j = 0; j <= min(n, i); ++j) {
                    for(int k = 0; k <= i; ++k) {
                        dp[i][j][k] = 0;
                    }
                }
            }
            dp[0][0][0] = 1;
            for(int i = 1; i <= m; ++i) {
                for(int j = 0; j <= min(n, i); ++j) {
                    for(int k = 0; k <= i; ++k) {
                        if(j && s[j-1] == '(') {
                            dp[i][j][k] = (dp[i][j][k]+dp[i-1][j-1][k-1])%mod;
                        }
                        if(j && s[j-1] == ')') {
                            dp[i][j][k] = (dp[i][j][k] + dp[i-1][j-1][k+1]) % mod;
                        }
                        if(j == 0 || s[j-1] == '(') {
                            dp[i][j][k] = (dp[i][j][k] + dp[i-1][j][k+1]) % mod;
                        }
                        if((j==0 || s[j-1] == ')') && k) {
                            dp[i][j][k] = (dp[i][j][k] + dp[i-1][j][k-1]) % mod;
                        }
                    }
                }
            }
            printf("%lld\n", dp[m][n][0]);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    L

    给出一个游戏,这个游戏的有多张有向图,编号分别从1到n。每张图上都有1到m个节点。玩家从第一张图开始出发,在每张图上可以选择移动一步,也可以选择不移动;假设操作后玩家所在的节点数是i,则他转移到下一张图的节点i。要求求出到达节点m的最小的使用图的数量。
    考虑使用动态规划解决问题,因为题目内存的限制,所以要用滚动数组来优化空间

    #include 
    #include 
    #include 
    
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 2010;
    
    // dp[i][j] 代表在第i个世界到达节点j所需的最小步数
    int d[maxn], dd[maxn], l, m, n;
    
    int main(void)
    {
        scanf("%d%d", &n, &m);
        memset(d, inf, sizeof d);
        d[1] = 1;
    
        while(n--) {
            scanf("%d", &l);
    
            for(int i = 1; i <= m; ++i) {  // 依次更新到达第i个节点的距离
                if(i > 1 && i < m && d[i] != inf)
                    ++d[i];
            }
    
            memcpy(dd, d, sizeof d);
    
            while(l--) {  // dp[i+1][j] = min(dp[i][j]+1, min(dp[i][u]+1)), 其中u->j有一条路
                int x, y;
                scanf("%d%d", &x, &y);
                dd[y] = min(dd[y], d[x]);
            }
    
            memcpy(d, dd, sizeof d);
        }
    
        printf("%d\n", d[m] == inf ? -1 : d[m]);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    数据库RDBMS1
    位、比特、字节、字、帧等概念关系的理解
    【入门-06】系统定时器
    springBoot集成mybatis-plus
    Java流程控制
    强化学习r
    Android-Handler源码解析-Message
    Packet Tracer路由器连接终端设备怎么配置?
    后厂村路灯:【干货分享】AppleDevelop苹果开发者到期重置
    Delphi指针相关学习
  • 原文地址:https://blog.csdn.net/apple_52296856/article/details/126484867