zoukankan      html  css  js  c++  java
  • 牛客-随机数

    题目传送门

    -------------------上个星期的假日团队赛,这题别人的代码看了四五天才明白,来补上代码

    sol1:排列组合,当考虑某一位本来是1的,现在改成了0,那么在这一位后面位的就可以随意排列组合了。

    • 排列组合
      #include "bits/stdc++.h"
      using namespace std;
      typedef long long LL;
      LL c[40][40];
      // 1100
      // 3210
      void init() {
          c[0][0] = 1;
          for (int i = 1; i <= 31; i++) {
              c[i][0] = 1;
              for (int j = 1; j <= i; j++)
              c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
          }
      }
      int slove(int n) {
          if (n == 0) return 0;
          int pos = 31, ans = 0;
          while ((n >> pos & 1) == 0) pos--;
          for (int i = pos - 1; i >= 1; i--) {
              for (int j = 0; j + 1<= (i + 1 >> 1); j++) ans += c[i][j];
          }
          int p = 1;
          for (int i = pos - 1; i >= 0; i--) {
              if (n >> i & 1) {
                  for (int j = 0; j + p <= (pos + 1 >> 1); j++) ans += c[i][j];
                  p++;
              }
          }
          if (p <= (pos + 1 >> 1)) ans++;
          return ans;
      }
      int main() {
          init();
          int l, r;
          scanf("%d%d", &l, &r);
          printf("%d
      ", slove(r) - slove(l - 1));
          return 0;
      }

    sol2:数位dp,别人的代码里有一块看了好久看不懂,看懂之后觉得是冗余。。。。不过思路可学

    • 数位dp
      #include "bits/stdc++.h"
      using namespace std;
      int dp[32][64]; // 表示考虑到第i位,01个数差为j的方案数,因为j可能是负数统一加32 
      bool dig[32];
      int dfs(int i, int j, bool lim, bool head) { //枚举到哪一位,sum0-sum1,限制,是否有第一个1 
          if (i < 1) return j == 32;
          if (!lim && head && ~dp[i][j]) return dp[i][j];
          int up = lim ? dig[i] : 1, sum = 0;
          // 第i位取0的情况 
          if (!head) sum += dfs(i - 1, j, false, false);
          else sum += dfs(i - 1, j - 1, lim && dig[i] == 0, true);
          // 第i位取1的情况 
          if (up) sum += dfs(i - 1, j + 1, lim, true);
          if (!lim && head) dp[i][j] = sum; 
          return sum;
      }
      int slove(int k) {
          int pos = 0, sum = 0;
          while (k) {
              dig[++pos] = k & 1;
              k >>= 1;
          }
          for (int i = 0; i <= pos; i++) sum += dfs(pos, i + 32, true, false);
          return sum;
      }
      int main() {
          int l, r;
          scanf("%d%d", &l, &r);
          memset(dp, -1, sizeof(dp));
          printf("%d
      ", slove(r) - slove(l - 1));
          return 0;
      }
  • 相关阅读:
    PHP发送邮件
    SQL删除字段及判断字段是否存在的方法
    密码MySQL的root的密码
    java socket 最简单的例子(server 多线程)
    php编写最简单的webservice
    SQL Server 存储过程与触发器
    手动创建最简单的JSP 文件
    Oracle 卸载步骤
    编写 WebService 程序
    eclipse 常用快捷键
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11185897.html
Copyright © 2011-2022 走看看