답안 #258672

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
258672 2020-08-06T10:57:40 Z cheeheng Lucky Numbers (RMI19_lucky) C++14
28 / 100
16 ms 2176 KB
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
typedef tuple<int, int, int, int> i4;
typedef tuple<ll, ll, ll, ll, ll, ll, ll, ll> i8;

const long long MOD = 1e9+7;

char S[100005];
int X[100005];
long long memo[10005][2];
long long dp2[100005][2];

int N, Q;
int K;

long long dp(int i, bool prev_digit_is_1, bool same_so_far){
    if(i == K){
        return 1;
    }else if(!same_so_far){
        if(prev_digit_is_1){
            return dp2[K-i][0];
        }else{
            return (dp2[K-i][1] + dp2[K-i][0])%MOD;
        }
    }else if(memo[i][prev_digit_is_1] != -1){
        return memo[i][prev_digit_is_1];
    }else{
        long long ans = 0;
        int j = X[i];
        if(j == 0){
            ans = dp(i+1, 0, 1);
        }else if(j == 1){
            ans = (dp(i+1, 0, 0) + dp(i+1, 1, 1))%MOD;
        }else if(j == 2){
            ans = (dp(i+1, 0, 0) + dp(i+1, 1, 0) + dp(i+1, 0, 1))%MOD;
        }else{
            ans = ((j-1-prev_digit_is_1)*dp(i+1, 0, 0) + dp(i+1, 1, 0) + dp(i+1, 0, 1))%MOD;
        }

        /*
        for(int j = 0; j < 10; j ++){
            if(j > X[i]){break;}
            if(prev_digit_is_1 && j == 3){
                continue;
            }

            ans += dp(i+1, j == 1, X[i] == j);
        }
        ans %= MOD;
        */

        //printf("memo[%d][%d][%d]=%lld\n", i, prev_digit_is_1, same_so_far, ans);
        return memo[i][prev_digit_is_1] = ans;
    }
}

// (first digit is 3, last digit is 1, same_so_far)
long long ways[5+(1<<18)][2][2][2];
int isMode[5+(1<<18)][2][2];

void init(int i = 1, int s = 0, int e = N-1){
    isMode[i][0][0] = (X[s] != 3 && X[e] != 1);
    isMode[i][0][1] = (X[s] != 3 && X[e] == 1);
    isMode[i][1][0] = (X[s] == 3 && X[e] != 1);
    isMode[i][1][1] = (X[s] == 3 && X[e] == 1);
    if(s == e){
        ways[i][0][0][0] = 8;
        ways[i][0][1][0] = 1;
        ways[i][1][0][0] = 1;
        ways[i][1][1][0] = 0;

        ways[i][0][0][1] = 0;
        ways[i][0][1][1] = 0;
        ways[i][1][0][1] = 0;
        ways[i][1][1][1] = 0;

        for(int j = 0; j <= X[s]; j ++){
            if(j == 3){
                ways[i][1][0][1] ++;
            }else if(j == 1){
                ways[i][0][1][1] ++;
            }else{
                ways[i][0][0][1] ++;
            }
        }
    }else{
        int l = (i<<1);
        int r = (i<<1)|1;
        int m = (s+e)>>1;

        init(l, s, m);
        init(r, m+1, e);

        /*
        22|22
        22|21
        22|32
        22|31
        21|22
        21|21

        32|22
        32|21
        32|32
        32|31
        31|22
        31|21

        (0, 0): 22|22, 22|32, 21|22
        (0, 1): 22|21, 22|31, 21|21
        (1, 0): 32|22, 32|32, 31|22
        (1, 1): 32|21, 32|31, 31|21

        */

        ways[i][0][0][0] = (ways[l][0][0][0]*ways[r][0][0][0] + ways[l][0][0][0]*ways[r][1][0][0]
                            + ways[l][0][1][0]*ways[r][0][0][0])%MOD;

        ways[i][0][1][0] = (ways[l][0][0][0]*ways[r][0][1][0] + ways[l][0][0][0]*ways[r][1][1][0]
                            + ways[l][0][1][0]*ways[r][0][1][0])%MOD;

        ways[i][1][0][0] = (ways[l][1][0][0]*ways[r][0][0][0] + ways[l][1][0][0]*ways[r][1][0][0]
                            + ways[l][1][1][0]*ways[r][0][0][0])%MOD;

        ways[i][1][1][0] = (ways[l][1][0][0]*ways[r][0][1][0] + ways[l][1][0][0]*ways[r][1][1][0]
                            + ways[l][1][1][0]*ways[r][0][1][0])%MOD;


        ways[i][0][0][1] = 0;
        ways[i][0][1][1] = 0;
        ways[i][1][0][1] = 0;
        ways[i][1][1][1] = 0;

        for(int a = 0; a < 2; a ++){
            for(int b = 0; b < 2; b ++){
                for(int c = 0; c < 2; c ++){
                    if(b&&c){continue;}
                    for(int d = 0; d < 2; d ++){
                        if( isMode[l][a][b] ){
                            ways[i][a][d][1] += (ways[l][a][b][1]+MOD-1)*ways[r][c][d][0]%MOD;
                            ways[i][a][d][1] += ways[r][c][d][1];
                        }else{
                            ways[i][a][d][1] += ways[l][a][b][1]*ways[r][c][d][0]%MOD;
                        }
                    }
                }
            }
        }

        ways[i][0][0][1] %= MOD;
        ways[i][0][1][1] %= MOD;
        ways[i][1][0][1] %= MOD;
        ways[i][1][1][1] %= MOD;

    }
    for(int j = 0; j < 8; j ++){
        //printf("s=%d e=%d [%d][%d][%d]: %lld\n", s, e, (int)((j&4)!=0), (int)((j&2)!=0), j&1, ways[i][(j&4)!=0][(j&2)!=0][j&1]);
    }
}

int k = 0;
long long tempL[31][2][2][2];
long long tempR[31][2][2][2];
long long newWays[31][2][2][2];
int isMode2[2][2];

i8 query(int x, int y, int i = 1, int s = 0, int e = N-1){
    if(s == 0 && e == N-1){k = 0;memset(newWays, 0, sizeof(newWays));}
    if(x <= s && e <= y){
        return i8(ways[i][0][0][0], ways[i][0][0][1], ways[i][0][1][0], ways[i][0][1][1],
                  ways[i][1][0][0], ways[i][1][0][1], ways[i][1][1][0], ways[i][1][1][1]);
    }else{
        int l = (i<<1);
        int r = (i<<1)|1;
        int m = (s+e)>>1;

        if(x > m){
            return query(x, y, r, m+1, e);
        }else if(y <= m){
            return query(x, y, l, s, m);
        }else{
            int cnt = k;
            k ++;

            i8 l1 = query(x, y, l, s, m);
            i8 r1 = query(x, y, r, m+1, e);

            int tempIndx = min(m, y);
            isMode2[0][0] = (X[x] != 3 && X[tempIndx] != 1);
            isMode2[0][1] = (X[x] != 3 && X[tempIndx] == 1);
            isMode2[1][0] = (X[x] == 3 && X[tempIndx] != 1);
            isMode2[1][1] = (X[x] == 3 && X[tempIndx] == 1);

            tempL[cnt][0][0][0] = get<0>(l1);
            tempL[cnt][0][0][1] = get<1>(l1);
            tempL[cnt][0][1][0] = get<2>(l1);
            tempL[cnt][0][1][1] = get<3>(l1);
            tempL[cnt][1][0][0] = get<4>(l1);
            tempL[cnt][1][0][1] = get<5>(l1);
            tempL[cnt][1][1][0] = get<6>(l1);
            tempL[cnt][1][1][1] = get<7>(l1);

            tempR[cnt][0][0][0] = get<0>(r1);
            tempR[cnt][0][0][1] = get<1>(r1);
            tempR[cnt][0][1][0] = get<2>(r1);
            tempR[cnt][0][1][1] = get<3>(r1);
            tempR[cnt][1][0][0] = get<4>(r1);
            tempR[cnt][1][0][1] = get<5>(r1);
            tempR[cnt][1][1][0] = get<6>(r1);
            tempR[cnt][1][1][1] = get<7>(r1);

            newWays[cnt][0][0][0] = (tempL[cnt][0][0][0]*tempR[cnt][0][0][0] + tempL[cnt][0][0][0]*tempR[cnt][1][0][0]
                                + tempL[cnt][0][1][0]*tempR[cnt][0][0][0])%MOD;

            newWays[cnt][0][1][0] = (tempL[cnt][0][0][0]*tempR[cnt][0][1][0] + tempL[cnt][0][0][0]*tempR[cnt][1][1][0]
                                + tempL[cnt][0][1][0]*tempR[cnt][0][1][0])%MOD;

            newWays[cnt][1][0][0] = (tempL[cnt][1][0][0]*tempR[cnt][0][0][0] + tempL[cnt][1][0][0]*tempR[cnt][1][0][0]
                                + tempL[cnt][1][1][0]*tempR[cnt][0][0][0])%MOD;

            newWays[cnt][1][1][0] = (tempL[cnt][1][0][0]*tempR[cnt][0][1][0] + tempL[cnt][1][0][0]*tempR[cnt][1][1][0]
                                + tempL[cnt][1][1][0]*tempR[cnt][0][1][0])%MOD;

            for(int a = 0; a < 2; a ++){
                for(int b = 0; b < 2; b ++){
                    for(int c = 0; c < 2; c ++){
                        if(b&&c){continue;}
                        for(int d = 0; d < 2; d ++){
                            if(isMode2[a][b]){
                                newWays[cnt][a][d][1] += (tempL[cnt][a][b][1]+MOD-1)*tempR[cnt][c][d][0]%MOD;
                                newWays[cnt][a][d][1] += tempR[cnt][c][d][1];
                            }else{
                                newWays[cnt][a][d][1] += tempL[cnt][a][b][1]*tempR[cnt][c][d][0]%MOD;
                            }
                        }
                    }
                }
            }

            return i8(newWays[cnt][0][0][0], newWays[cnt][0][0][1], newWays[cnt][0][1][0], newWays[cnt][0][1][1],
                  newWays[cnt][1][0][0], newWays[cnt][1][0][1], newWays[cnt][1][1][0], newWays[cnt][1][1][1]);
        }
    }
}

int main(){
    scanf("%d%d", &N, &Q);
    scanf(" %s", S);

    for(int i = 0; i < N; i ++){
        X[i] = S[i]-'0';
    }

    dp2[0][0] = 1;
    dp2[0][1] = 0;
    for(int i = 1; i <= N; i ++){
        dp2[i][0] = (dp2[i-1][1]*8 + dp2[i-1][0]*9)%MOD;
        dp2[i][1] = (dp2[i-1][1] + dp2[i-1][0])%MOD;
        //printf("dp2[%d][%d]=%lld\n", i, 0, dp2[i][0]);
        //printf("dp2[%d][%d]=%lld\n", i, 1, dp2[i][1]);
    }

    K = N;
    memset(memo, -1, sizeof(memo));
    //printf("%lld\n", dp(0, false, true));
    init();
    i8 temp = query(0, N-1);
    long long ans = 0;
    ans += get<1>(temp);
    ans += get<3>(temp);
    ans += get<5>(temp);
    ans += get<7>(temp);
    ans %= MOD;
    printf("%lld\n", ans);

    for(int i = 0; i < Q; i ++){
        int t, l, r;
        scanf("%d%d%d", &t, &l, &r);

        if(t == 2){
            S[l-1] = r+'0';
            X[l-1] = r;
            init();
        }else{
            //printf("%s\n", S);;
            i8 temp = query(l-1, r-1);
            long long ans = 0;
            ans += get<1>(temp);
            ans += get<3>(temp);
            ans += get<5>(temp);
            ans += get<7>(temp);
            ans %= MOD;
            assert(ans >= 0);
            printf("%lld\n", ans);

            /*l --;
            r --;
            for(int j = 0; j < r-l+1; j ++){
                X[j] = S[l+j]-'0';
            }
            K = r-l+1;
            memset(memo, -1, sizeof(memo));
            printf("%lld\n", dp(0, false, true));*/
        }
    }

    return 0;
}

Compilation message

lucky.cpp: In function 'int main()':
lucky.cpp:249:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d%d", &N, &Q);
     ~~~~~^~~~~~~~~~~~~~~~
lucky.cpp:250:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf(" %s", S);
     ~~~~~^~~~~~~~~~
lucky.cpp:280:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d%d%d", &t, &l, &r);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 512 KB Output is correct
2 Correct 0 ms 512 KB Output is correct
3 Correct 0 ms 512 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 512 KB Output is correct
2 Correct 0 ms 512 KB Output is correct
3 Correct 0 ms 512 KB Output is correct
4 Correct 0 ms 512 KB Output is correct
5 Correct 0 ms 512 KB Output is correct
6 Correct 0 ms 512 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Incorrect 16 ms 2176 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 16 ms 2176 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 512 KB Output is correct
2 Correct 0 ms 512 KB Output is correct
3 Correct 0 ms 512 KB Output is correct
4 Correct 0 ms 512 KB Output is correct
5 Correct 0 ms 512 KB Output is correct
6 Correct 0 ms 512 KB Output is correct
7 Incorrect 16 ms 2176 KB Output isn't correct
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 512 KB Output is correct
2 Correct 0 ms 512 KB Output is correct
3 Correct 0 ms 512 KB Output is correct
4 Correct 0 ms 512 KB Output is correct
5 Correct 0 ms 512 KB Output is correct
6 Correct 0 ms 512 KB Output is correct
7 Incorrect 16 ms 2176 KB Output isn't correct
8 Halted 0 ms 0 KB -