zoukankan      html  css  js  c++  java
  • hdu 5587 Array

      题目链接:hdu 5587

      前两周 bc 上的题了,因为赶大作业所以没有去打,看了下官方给出的思路,感觉好强大~~竟然能转化成求二进制数 1 的个数:

      然后数位 dp 就行了,

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef unsigned long long ull;
     6 #define  For(i,s,t)  for(int i = s; i <= t; ++i)
     7 
     8 ull C[60][60];      // 组合数
     9 inline void init_C(int n) {
    10     For(i,0,n)  C[i][0] = 1;
    11     For(i,1,n)  For(j,1,i) {
    12         C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
    13     }
    14 }
    15 
    16 // dp[i] 表示所有 i 位二进制数里'1'的个数总数,p2[i] 即 i 位二进制数的总个数
    17 ull dp[60], p2[60] = {1, 2};
    18 inline void init(int n = 56) {
    19     init_C(n);
    20     for(int i = 1; i <= n; ++i)
    21         for(int j = 1; j <= i; ++j)
    22             dp[i] += j * C[i][j];
    23     For(i,2,n)
    24         p2[i] = p2[i - 1] * 2;
    25 }
    26 
    27 int digit[60];       // digit 数组保存的是 x 的二进制表示法
    28 ull solve(ull x) {
    29     int len = 0;
    30     while(x) {
    31         digit[++len] = x % 2;
    32         x /= 2;
    33     }
    34     int num1 = 0;           // num1 记录的是 digit 里第 i 位前面的'1'的个数
    35     ull res = 0;
    36     for(int i = len; i; --i) {
    37         // 只处理第 i 位为'1'的情况就行,'0'的话在该位没有比它更小的了,所以不用处理
    38         if(digit[i] == 1) {
    39             // p2[i - 1] * num1 统计的是第 i 位前面的'1'的个数总数(因为此时第 i 位取'0',后面的 i-1 位可以任取)
    40             // dp[i - 1] 统计后面 i-1 位里'1'的个数总数
    41             res += p2[i - 1] * num1 + dp[i - 1];
    42             ++num1;
    43         }
    44     }
    45     return res;
    46 }
    47 
    48 int main() {
    49     int t;
    50     ull m;
    51     init();
    52     scanf("%d",&t);
    53     while(t--) {
    54         scanf("%I64u",&m);
    55         printf("%I64u
    ",solve(m + 1));     // 因为上面统一处理的是比 x 小的数,所以在这里 +1
    56     }
    57     return 0;
    58 }
    View Code

      网上好像有很多思路可以递归或者递推找规律的,我学习了下,感觉也很强大:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef unsigned long long ull;
     6 const int N = 103;
     7 const ull maxLen = 1e16 + 8;
     8 
     9 ull preLen[N], preSum[N];
    10 
    11 inline void init(int n = 101) {
    12     preLen[1] = preSum[1] = 1;
    13     for(int i = 2; i <= n; ++i) {
    14         preLen[i] = preLen[i - 1] * 2 + 1;
    15         preSum[i] = preSum[i - 1] * 2 + (preLen[i] - preLen[i - 1]);
    16         if(preLen[i] > maxLen)  return ;
    17     }
    18 }
    19 
    20 ull dfs(ull mlen) {
    21     if(mlen == 0)   return 0;
    22     int pos;
    23     for(int i = 1; i <= 101; ++i) {
    24         if(mlen < preLen[i + 1]) {
    25             pos = i;
    26             break;
    27         }
    28     }
    29     ull remainLen = (mlen == preLen[pos] ? 0: mlen - preLen[pos] - 1);
    30     return preSum[pos] + dfs(remainLen) + (mlen - preLen[pos]);
    31 }
    32 
    33 int main() {
    34     init();
    35     int t;
    36     ull m;
    37     scanf("%d",&t);
    38     while(t--) {
    39         scanf("%I64u",&m);
    40         printf("%I64u
    ",dfs(m));
    41     }
    42     return 0;
    43 }
    View Code

      因为不是比赛时做,所以时间比较充裕,变量名写得有点长了,看着像在写工程代码

      这题,必须好好琢磨才行,它和刚过去的 2015CCPC 南阳的热身赛的第一题很像,都是递归的思想,当时现场想不出来,却被身旁的师弟秒掉了,好惭愧的感觉 -_-||   看来自己还要勤加练习啊,弱渣就需多努力~

      顺便贴一下 5586 Sum 的代码,自己1A掉的:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N = 100005;
     6 #define  For(i,s,t)  for(int i = s; i <= t; ++i)
     7 
     8 int a[N], b[N];
     9 
    10 inline int trans(const int &x) {
    11     return (1890 * x + 143) % 10007;
    12 }
    13 
    14 int maxSum(int *b, int n) {
    15     int res = b[1], cur = b[1];
    16     for(int i = 2; i <= n; ++i) {
    17         cur = max(cur + b[i], b[i]);
    18         res = max(res, cur);
    19     }
    20     return max(res, 0);
    21 }
    22 
    23 int main() {
    24     int n;
    25     while(~scanf("%d",&n)) {
    26         int sum = 0;
    27         For(i,1,n) {
    28             scanf("%d",a + i);
    29             sum += a[i];
    30             b[i] = trans(a[i]) - a[i];
    31         }
    32         printf("%d
    ", sum + maxSum(b, n));
    33     }
    34     return 0;
    35 }
    View Code
  • 相关阅读:
    高级查询及分页总结
    SQL编程
    线程同步
    创建和启动线程
    错题集04
    错题集03
    错题集02
    错题集
    新闻发布系统
    九大内置对象
  • 原文地址:https://www.cnblogs.com/Newdawn/p/5030778.html
Copyright © 2011-2022 走看看