The 16th Xidian University Program Design Competition Network Synchronization Competition - Xieldy And His Password (Looking for patterns/ideas)

The 16th Xidian University Program Design Competition Network Synchronization Competition - Xieldy And His Password (Looking for patterns/ideas)

Topic link: Xieldy And His Password


meaning of the title

As we all know, Xieldy's most commonly used password is ** .
In order to change this situation, he randomly created a string of 01, and intercepted a section from it as his own password.
The password he chooses satisfies the following conditions:

  1. The binary number represented by the password string can be represented as 3k (k>=0) in decimal.
  2. The password string can have leading zeros.

    Now that 01 strings have been randomly generated, he wants to know how many password schemes can be selected (different subsections are different).

Enter description:

若干组数据,每组数据仅一行01串s,表示random出来的的串,|s|<=1e6

Output description:

输出口令的方案数。

idea one

​ Since the requirement of the title is to find a 01 string that can be divisible by three when it is converted into decimal, then we will find out what is the law of the binary representation of a multiple of three. Then, I started a long night of exploration. Unfortunately, I didn't find anything. However, after the competition, a classmate told me the law he found, that is, if a binary number is a multiple of three, then its A 1 in an odd and even digit must differ by a multiple of 3.

​ 0 11 110 1001 10101 These examples all satisfy

Then we can think about it. I constructed a sum array with a size of three, and recorded the number of combinations of the previous parity difference of 0, 1, and 2; respectively.

for example

At 000000, the initial sum[0] = 1, sum[1] = sum[2] = 0;

In the process of moving to the left each time, calculate the current parity difference, if the difference is 0, access sum[0], the number of combinations related to the current bit is the number of the previous parity difference of 0 plus one


code one

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)(j);i <= (int)(k);i ++)
#define per(i,j,k) for(int i = (int)(j);i >= (int)(k);i --)
#define mmm(a,b)   memset(a,b,sizeof(a))

typedef long long LL;
const int INF = (int)0x3f3f3f3f;
const LL MAXN = (LL)2e6+7;

char str[MAXN];
LL sum[3];
LL odd,eve;
LL ans;

void init(){
    mmm(sum,0);
    sum[0] = 1;
    ans = 0;
    odd = eve = 0;
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    while (cin >> str){
        init();
        LL len = strlen(str);
        rep(i,0,len-1){
            if (i&1) odd += str[i]-'0';
            else     eve += str[i]-'0';

            LL cha = ((odd-eve)%3+3)%3;//特别要注意这个操作,不能直接取绝对值,这样会破坏奇偶的差值
            ans += sum[cha];
            sum[cha] += 1;
        }
        cout << ans << endl;
    }
}

idea two

Dynamic programming
01 String s, length n
dp[i][j]: Ended with s[i], the number of solutions that can be divided by 3 with remainder j (0<=i<=n1, 0<=j<= 2)
Update the dp array from left to right

  • If s[i] is '0', the number ending with s[i] is equivalent to the number ending with s[i1]*2

    3k*2 = 6*k remainder 0
    (3k+1)*2 = 6*k+2 remainder 2
    (3k+2)*2 = 6*k+4 remainder 1
    and then consider s[i] alone as a number 0 Case
    So
    dp[i].[0] = dp[i-1].[0]+1
    dp[i].[1] = dp[i-1].[2]
    dp[i].[2] = dp[i-1].[1]

  • If s[i] is '1', the number ending with s[i] is equivalent to the number ending with s[i1]*2+1

    3k*2+1 = 6*k+1 remainder 1
    (3k+1)*2+1 = 6*k+3 remainder 0
    (3k+2)*2+1 = 6*k+5 remainder 2
    and then consider s [i] is the number 1 alone,
    so
    dp[i].[0] = dp[i-1].[1]
    dp[i].[1] = dp[i-1].[0]+1
    dp[i].[2] = dp[i-1].[2]
    ans = Σdp[i].[0]
    Time complexity O(n)

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)(j);i <= (int)(k);i ++)
#define per(i,j,k) for(int i = (int)(j);i >= (int)(k);i --)
#define mmm(a,b)   memset(a,b,sizeof(a))

typedef long long ll;
const int INF = (int)0x3f3f3f3f;
const int MAXN = (int)1e6+7;

char str[MAXN];
ll dp[MAXN][3];
ll sum;

void init(){
    dp[0][0] = 0;
    dp[0][1] = dp[0][2] = -1;
    sum = 0;
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    while (cin >> str+1){
        init();
        ll len = strlen(str+1);
        rep(i,1,len){
            if (str[i] == '0'){
                dp[i][0] = dp[i-1][0]+1;
                dp[i][1] = dp[i-1][2];
                dp[i][2] = dp[i-1][1];
            }else {
                dp[i][0] = dp[i-1][1]+1;
                dp[i][1] = dp[i-1][0];
                dp[i][2] = dp[i-1][2];
            }
            sum += dp[i][0];
        }
        cout << sum << endl;
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324891610&siteId=291194637