CSU2069: Saruman’s Level Up

原创 2018年04月15日 21:04:10

Description

Saruman’s army of orcs and other dark minions continuously mine and harvest lumber out of the land surrounding his mighty tower for N continuous days. On day number i, Saruman either chooses to spend resources on mining coal and harvesting more lumber, or on raising the level (i.e., height) of his tower. He levels up his tower by one unit only on days where the binary representation of i contains a total number of 1’s that is an exact multiple of 3. Assume that the initial level of his tower on day 0 is zero. For example, Saruman will level up his tower on day 7 (binary 111), next on day 11 (binary 1011) and then day 13, day 14, day 19, and so on. Saruman would like to forecast the level of his tower after N days. Can you write a program to help?

Input

The input file will contain multiple input test cases, each on a single line. Each test case consists of a positive integer N < 1016, as described above. The input ends on end of file.

Output

For each test case, output one line: “Day N: Level = L”, where N is the input N, and L is the number of levels after N days.

Sample Input

2
19
64

Sample Output

Day 2: Level = 0
Day 19: Level = 5
Day 64: Level = 21

Hint

Source

pacnw2012

题意:如果一个数n的二进制表示中的1的个数为3的倍数,那么这个数可以让高度加1。题目给定n,问从0到n一共有多少个数使得高度加1。

题解:首先我们求出给定数的二进制表示,对于该数字,我们可以将其分解成0 - 1111111...(比原先位数少1) 和 最高位10000000... -二进制表示数。对于0 - 1111111...这个范围,3的倍数的1的数量为C(n, 3) + C(n, 6) + ....C(n, x)(x <= n)。同理,对于最高位10000000... -二进制表示数,进行相同的操作分解。注意,因为此时最高位1一定存在,故之后应求解C(m, 2) + C(m, 5) + ...C(m, x)(x <= m)。同时我们注意到,每当3变成0时,当前的值也是一种解,故每次变成0答案加1。


AC代码

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <stdio.h>
#include <cmath>
#include <sstream>
typedef long long ll;

using namespace std;

const int maxn = 100;
struct bign{
    int d[maxn], len;

    void clean() { while(len > 1 && !d[len-1]) len--; }

    bign()          { memset(d, 0, sizeof(d)); len = 1; }
    bign(int num)   { *this = num; }
    bign(char* num) { *this = num; }
    bign operator = (const char* num){
        memset(d, 0, sizeof(d)); len = strlen(num);
        for(int i = 0; i < len; i++) d[i] = num[len-1-i] - '0';
        clean();
        return *this;
    }
    bign operator = (int num){
        char s[20]; sprintf(s, "%d", num);
        *this = s;
        return *this;
    }

    bign operator + (const bign& b){
        bign c = *this; int i;
        for (i = 0; i < b.len; i++){
            c.d[i] += b.d[i];
            if (c.d[i] > 9) c.d[i]%=10, c.d[i+1]++;
        }
        while (c.d[i] > 9) c.d[i++]%=10, c.d[i]++;
        c.len = max(len, b.len);
        if (c.d[i] && c.len <= i) c.len = i+1;
        return c;
    }
    bign operator - (const bign& b){
        bign c = *this; int i;
        for (i = 0; i < b.len; i++){
            c.d[i] -= b.d[i];
            if (c.d[i] < 0) c.d[i]+=10, c.d[i+1]--;
        }
        while (c.d[i] < 0) c.d[i++]+=10, c.d[i]--;
        c.clean();
        return c;
    }
    bign operator * (const bign& b)const{
        int i, j; bign c; c.len = len + b.len;
        for(j = 0; j < b.len; j++) for(i = 0; i < len; i++)
            c.d[i+j] += d[i] * b.d[j];
        for(i = 0; i < c.len-1; i++)
            c.d[i+1] += c.d[i]/10, c.d[i] %= 10;
        c.clean();
        return c;
    }
    bign operator / (const bign& b){
        int i, j;
        bign c = *this, a = 0;
        for (i = len - 1; i >= 0; i--)
        {
            a = a*10 + d[i];
            for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
            c.d[i] = j;
            a = a - b*j;
        }
        c.clean();
        return c;
    }
    bign operator % (const bign& b){
        int i, j;
        bign a = 0;
        for (i = len - 1; i >= 0; i--)
        {
            a = a*10 + d[i];
            for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
            a = a - b*j;
        }
        return a;
    }
    bign operator += (const bign& b){
        *this = *this + b;
        return *this;
    }

    bool operator <(const bign& b) const{
        if(len != b.len) return len < b.len;
        for(int i = len-1; i >= 0; i--)
            if(d[i] != b.d[i]) return d[i] < b.d[i];
        return false;
    }
    bool operator >(const bign& b) const{return b < *this;}
    bool operator<=(const bign& b) const{return !(b < *this);}
    bool operator>=(const bign& b) const{return !(*this < b);}
    bool operator!=(const bign& b) const{return b < *this || *this < b;}
    bool operator==(const bign& b) const{return !(b < *this) && !(b > *this);}

    string str() const{
        char s[maxn]={};
        for(int i = 0; i < len; i++) s[len-1-i] = d[i]+'0';
        return s;
    }
};

bign pack[1000001];

istream& operator >> (istream& in, bign& x)
{
    string s;
    in >> s;
    x = s.c_str();
    return in;
}

ostream& operator << (ostream& out, const bign& x)
{
    out << x.str();
    return out;
}


ll num;
bign ans;

string a;
void get_two(ll n){
    string b, c;
    while(n){
        b += (n % 2) + '0';
        n /= 2;
    }
    for(ll i = 0; i < b.length(); i++)
        c += b[b.length() - 1 - i];
    a = c;
}

ll loc[111];

double lnchoose(ll n, ll m){
    if(m > n)
        return 0;
    if(m < n / 2.0)
        m = n - m;
    double s1 = 0;
    for(ll i = m + 1; i <= n; i++)
        s1 += log(double(i));
    double s2 = 0;
    ll ub = n - m;
    for(ll i = 2; i <= ub; i++)
        s2 +=log(double(i));
    return s1 - s2;
}

bign choose(ll n, ll m){
    if(m > n)
        return 0;
    bign ans(1);
    for (int i = 1; i <= min(m, n - m); i++)
        ans = ans * bign(n - i + 1);
    for (int i = 1; i <= min(m, n - m); i++)
        ans = ans / bign(i);
    return ans;
}

void solve(ll x, ll nn){
    x = a.length() - x - 1;
    while(x >= nn){
        bign k = choose(x,nn);
//        cout << k << " " << x << " " << nn << endl;
        ans += k;
        nn += 3;
    }
}

int main(){
    ll n;

    while(scanf("%lld", &n) != EOF){
        get_two(n);
        num = 1;
        for(ll i = 0; i < a.length(); i++)
            if(a[i] == '1')
                loc[num++] = i;
        ans = bign(0);
        ll nn = 3;
        for(ll i = 1; i < num; i++){
            solve(loc[i], nn);
            nn--;
            if(nn == 0)
                ans = ans + bign(1), nn += 3;
        }
        printf("Day %lld: Level = %s\n", n, ans.str().c_str());
    }
    return 0;
}

CSU 2069 Saruman’s Level Up(组合数+枚举)

CSU 2069 Saruman’s Level Up 题意 ​ 求0-n之间,二进制中1的个数为3的倍数的数有多少个。 解题思路   首先我们知道,剩余位数=length-1-当...
  • qq_36258516
  • qq_36258516
  • 2018-04-17 07:59:04
  • 87

CSU 2070 Seating Chart(线段树求逆序数)

CSU 2070 Seating Chart 题意 ​ 给出一个序列,求第二个序列的逆序数。 解题思路   如果直接暴力求解,肯定会TLE。队友是用归并排序过的,我重新写了遍线段树...
  • qq_36258516
  • qq_36258516
  • 2018-04-18 20:56:44
  • 11

2069: Saruman’s Level Up(思维枚举+质数分解求组合数)

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2069 题目: Description Saruman’s army of or...
  • qq_36300700
  • qq_36300700
  • 2018-04-16 20:34:54
  • 117

POJ3069 Saruman's Army

Saruman's Army Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4214   ...
  • u012846486
  • u012846486
  • 2014-10-30 11:31:32
  • 840

Saruman's Army

#include #include #include using namespace std;#define MAX_N 2000int N,R; int X[MAX_N];void solve(...
  • NoMasp
  • NoMasp
  • 2015-05-19 15:17:11
  • 2066

CSU2069: Saruman’s Level Up

DescriptionSaruman’s army of orcs and other dark minions continuously mine and harvest lumber out of...
  • qq_37064135
  • qq_37064135
  • 2018-04-15 21:04:10
  • 82

sas统计分析学习笔记(一)

一.基本规则 1.DATA步骤:定义数据和创建数据集,以DATA 开始,以DATALINES结束;PROC步骤:定义统计分析的类型,每个PROC过程后接一个run语句。 2.SAS变量名必须遵循以下原...
  • csutxy
  • csutxy
  • 2017-08-05 16:07:19
  • 369

Poj 3069 Saruman's Army【贪心】

Saruman's Army Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5742   Accepted: 2...
  • liuke19950717
  • liuke19950717
  • 2015-10-01 22:57:45
  • 1045

HDU 3954 Level up(线段树的区间更新+小技巧)

Level up is the task of all online games. It's very boooooooooring. There is only level up in those ...
  • qq_37497322
  • qq_37497322
  • 2017-08-03 10:24:24
  • 332

CSU 1813 盖房子

Description Bobo 在 ICPCCamp 买了一块 n×m 的土地,其中有些格子是障碍。 他想选择两个矩形区域,建造两座房子。 很明显,用于盖房子的区域不能包含障碍。同时,两个区...
  • jtjy568805874
  • jtjy568805874
  • 2016-09-05 18:37:03
  • 403
收藏助手
不良信息举报
您举报文章:CSU2069: Saruman’s Level Up
举报原因:
原因补充:

(最多只允许输入30个字)