zoukankan      html  css  js  c++  java
  • Codeforces#572 Div2 C---Candies!【倍增】【DP】【思维】

    题目http://codeforces.com/contest/1189/problem/C

    题意:给定n个数,每次查询一个区间$[l,r]$。对这个区间内的数,相邻两个数之和超过10,则得到一个candy,然后将他们之和取模10的结果作为新的数。

    一共操作$l-r$次,问这个区间得到的candy数。

    思路:一种思路是可以发现,实际上candy数是和/10,而新得到的数实际上是/10之后的小数部分。

    每次操作的过程其实可以看成是两两求和然后取/10的整数部分,然后把小数部分再两两求和取整数部分,剩下的再留给下一次操作。

    所以$ans[l,r] = lfloor frac{a_l+a_{l+1}+...+a_r}{10} floor$

    另一种思路是用倍增的思想进行dp。

    $dp[i][k]$表示以$i$为开头,$2^k$个数所得到的candy数。因为转移的时候还需要知道当前操作之后的数是什么,所以用$dig[i][k]$记录对应操作后的数。

    $dp[i][k] = dp[i][k-1]+dp[i + 2^{k-1}][k-1] +(dig[i][k-1] + dig[i + 2^{k-1}][k-1] ge 10)$

    DP解法

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x3f3f3f3f
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<int, int> pr;
    17 
    18 const int maxn = 1e5 + 5;
    19 int n, q;
    20 int num[maxn];
    21 int dp[maxn][20], dig[maxn][20];
    22 
    23 int main()
    24 {
    25     scanf("%d", &n);
    26     for(int i = 1; i <= n; i++){
    27         scanf("%d", &num[i]);
    28         dp[i][0] = 0;
    29         dig[i][0] = num[i];
    30     }
    31     int pow = 2;
    32     for(int k = 1; k < 20; k++, pow *= 2){
    33         for(int i = 1; i + pow <= n + 1; i++){
    34             dp[i][k] = dp[i][k - 1] + dp[i + pow / 2][k - 1];
    35             if(dig[i][k - 1] + dig[i + pow / 2][k - 1] >= 10)dp[i][k]++;
    36             dig[i][k] = (dig[i][k - 1] + dig[i + pow / 2][k - 1]) % 10;
    37         }
    38     }
    39     scanf("%d", &q);
    40     while(q--){
    41         int l, r;
    42         scanf("%d%d", &l, &r);
    43         int k = 0, seg = r - l + 1;
    44         while(seg % 2 == 0){
    45             k++;
    46             seg >>= 1;
    47         }
    48         printf("%d
    ", dp[l][k]);
    49     }
    50     return 0;
    51 }

    公式解法:

    #include<cstdio>
    #include<cstdlib>
    #include<map>
    #include<set>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath> 
    #include<stack>
    #include<queue>
    #include<iostream>
    
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pr;
    
    const int maxn = 1e5 + 5;
    int n, q;
    int num[maxn], sum[maxn];
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d", &num[i]);
            sum[i] = sum[i - 1] + num[i];
        }
        scanf("%d", &q);
        while(q--){
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d
    ", (sum[r] - sum[l - 1]) / 10);
        }
        
        return 0;
    }
  • 相关阅读:
    Sql优化思路
    「网络流随想随记」
    「ZJOI 的部分题解整理」
    「循环矩阵相关的一些东西」
    知识蒸馏
    3D Human Pose Estimation with 2D Marginal Heatmaps
    模型剪枝
    目标检测小网络
    selenium---解决clear方法失效
    selenium---快速跳转到指定元素
  • 原文地址:https://www.cnblogs.com/wyboooo/p/11153973.html
Copyright © 2011-2022 走看看