SRM514 Div2 Hard(1000) MagicalGirlLevelThreeDivTwo

MagicalGirlLevelThreeDivTwo

hi-lo≦1000という制約があるので、1ビットごとに0か1かを調べる。事前に各要素の長さを求めておけば、O(n2)で辿ることができる。文字列長はlong longで表現できる長さを超えうるけど、hi≦1015という制約があるので、1015以上の適当な値を入れておけば良い。

サンプルインプットの4個目のバイトを1つの文字列に固めてから16ビットずつに区切ってShiftJISるととマミさんの必殺技の名前になる

https://twitter.com/kyuridenamida/status/101255069755916289

www 気付かなかった。

#include <string>
#include <vector>
using namespace std;

int getbit( vector<string> first, vector<long long> L, int s, long long p )
{
    int K = (int)first.size();

    if ( s < K )
    {
        return first[s][(int)p]-'0';
    }
    else
    {
        long long t = 0;
        for ( int i=s-1; ; i-=K )
        {
            if ( p < t+L[i] )
                return getbit(first,L,i,p-t);
            t += L[i];
        }
    }
}

class MagicalGirlLevelThreeDivTwo{public:
int theCount( vector <string> first, int n, long long lo, long long hi )
{
    long long M = 1000000000000000ll;

    int K = (int)first.size();

    vector<long long> L(n+1);
    for ( int i=0; i<=n; i++ )
        if ( i < K )
            L[i] = first[i].size();
        else
            for ( int j=i-1; j>=0; j-=K )
                L[i] += L[j],
                L[i] = min( L[i], M );
    
    int ans = 0;
    for ( long long i=lo; i<=hi; i++ )
        ans += getbit( first, L, n, i );
    return ans;
}};