zoukankan      html  css  js  c++  java
  • 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) D题(dp)

    https://codeforc.es/gym/101982

    题意

    给定k,b两个数,求在0到2^b-1区间中是k的倍数的数的二进制数中1的个数的总和。

    题解

    dp。

    d[i][j]表示:前二进制长度为i的数中模k为j的数的二进制数里1的个数的总和。(所以最终答案就是d[b][0])

    f[i][j]表示: 前二进制长度为i的数中模k为j的数的个数。

    转移:

    d[i][j]=d[i-1][j]+d[i-1][j-2^(i-1)%k]+f[i-1][j-2^(i-1)%k]

    f[i][j]=f[i-1][j]+f[i-1][j-2^(i-1)%k];

    代码:(来自ccsu_cat,使用了滚动数组优化)

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int maxn = 1010, mod = 1e9 + 9;
     5 ll d[2][maxn] ,f[130][maxn];
     6 void add(ll &x, ll y) {
     7     x = (x + y) % mod;
     8 }
     9 int gao(int x) {
    10     if (!x)
    11         return 0;
    12     return gao(x / 2) + (x % 2);
    13 }
    14 int main () {
    15     int n, k, p = 1, m = 1, s = 1, cur = 0;
    16     cin>>k>>n;
    17     for (m = 1; m < k && s < n; m <<= 1)
    18         p = p * 2 % k, s++;
    19     for (int i = 0; i < m && (i < (1 << s)); i++) {
    20         d[cur][i % k] += gao(i);
    21         f[cur][i % k]++;
    22     }
    23     for (int i = s; i <= n; i++) {
    24         cur = !cur;
    25         for (int j = 0; j < k; j++) {
    26             d[cur][j] = d[!cur][j];
    27             int q = (j - p + k) % k;
    28             add(d[cur][j], d[!cur][q] + f[!cur][q]);
    29             f[cur][j] = f[!cur][j];
    30             add(f[cur][j], f[!cur][q]);
    31         }
    32         p = p * 2 % k;
    33     }
    34     cout<<d[cur][0];
    35 }
  • 相关阅读:
    <hdu2072>单词数(set容器,string类应用)
    志愿者选拔
    Game of Life
    <LightOJ 1338> Hidden Secret!
    Miss Kitty and Her Little Ice Cream Shop(水题)
    约瑟夫问题
    <FZU 1019>猫捉老鼠
    <cf>System of Equations(水题)
    Palindromic Numbers (III)(回文数,较麻烦)
    <cf>Solitaire(DFS or DP)
  • 原文地址:https://www.cnblogs.com/ccsu-kid/p/11135201.html
Copyright © 2011-2022 走看看