Topcoder 12728 - Flipping Bits Div1

 

Problem Link:

 

https://community.topcoder.com/stat?c=problem_statement&pm=12728

 


 

Problem Statement:

 

Goose Tattarrattat has a sequence B of bits. The length of the sequence is N. Tattarrattat also has a favorite integer M which is between 1 and N, inclusive.

 

A sequence of N bits is called a rotator sequence if it has the following property: its prefix of length N-M is equal to its suffix of length N-M.

 

For example, let M=2. Consider the sequence B="10101010". Its length is N=8, so we have N-M=6. The prefix of length 6 is "101010", the suffix of length 6 is "101010". They are the same, so this B is a rotator sequence. Now consider B="11010100". For this B we compare the prefix "110101" to the suffix "010100". They differ, so this B is not a rotator sequence.

 

Tattarrattat wants to change her sequence B into some rotator sequence. She will produce such a sequence in a sequence of steps. In each step she can do one of the following two types of changes to the sequence:

 

  • Flip any bit (from 1 to 0 or from 0 to 1).
  • Flip the first k*M bits, for any positive integer k.

 

You are given a String[] S and the int M. Concatenate all elements of S to obtain one long String. This String will represent the sequence B: each of its characters will be either '0' or '1'. Return the minimal number of steps required to obtain some rotator sequence.

 

Definition:

 

Class:           FlippingBitsDiv1

Method:               getmin

Parameters:           vector <string>, int

Returns:                 int

Method signature:          int getmin(vector <string> S, int M)

(be sure your method is public)

 

Constraints:

 

-          S will contain between 1 and 6 elements, inclusive.

-          Each element of S will contain between 1 and 50 characters, inclusive.

-          Each character in each element of S will be '0' or '1'.

-          M will be between 1 and N, where N is the total number of characters in S.

 

Limits:

 

Time limit (s):     

840.000

Memory limit (MB):  64

 


 

 

Analysis:

 

The first thing we should notice is that any rotator sequence with a specific M can be obtained from concatenating the same string of M bits length with itself several times, which is to say, any rotator sequence is determined by its first M bits.

 

After that, we might want to solve this problem with the help of bit masking. True, but this can only be done when M is small enough. Otherwise, the number of possible masks (2M) will be too large for us to enumerate. Let us move on to get more insights.

 

Another thing that can be noticed is that when M is large, the final string we have can be obtained from just replicating the first M bits a few times (we don’t need to concatenate a lot of times when M is large). For example, when the total length of the string is 500 and M is 50, we only need to replicate the first 50 bits 10 times to obtain a rotator sequence. Let us call each replicate of the first M bits a block, then when M is large, the number of blocks is small.

Thus, with just a few blocks, we can try enumerating if we will flip the first k blocks for all blocks, and this information can also be stored through bit masking.

 

Let us move to our conclusion. When M is small, we enumerate through the final prefix of M bits we might have and then use dynamic programming to get the minimum number of moves. When M is large, we enumerate through the possible flips of the blocks, and then greedily choose which single bits (among the positions that coincide when taking modulo M) we should flip (of course flip as little times as possible). We can choose this bound of M to be square root of N, and the masks we need to enumerate through will be small enough for us to handle (less than 218).

 


 

 

Time Complexity:

 

O(n2√n) (n for the length of the string)

 


 

 

AC Code:

 

  1 #include <iostream>
  2 #include <sstream>
  3 #include <fstream>
  4 #include <string>
  5 #include <vector>
  6 #include <deque>
  7 #include <queue>
  8 #include <stack>
  9 #include <set>
 10 #include <map>
 11 #include <algorithm>
 12 #include <functional>
 13 #include <utility>
 14 #include <bitset>
 15 #include <cmath>
 16 #include <cstdlib>
 17 #include <ctime>
 18 #include <cstdio>
 19 #include <memory.h>
 20 #include <functional>
 21 #include <string.h>
 22 #include <iomanip>
 23 #include <unordered_set>
 24 #include <unordered_map>
 25 using namespace std;
 26 
 27 typedef long long ll;
 28 typedef pair<int,int> pi; 
 29 typedef double db;
 30 
 31 const int mod=1e9+7;
 32 ll qpow(ll x,ll k){return k==0?1:1ll*qpow(1ll*x*x%mod,k>>1)*(k&1?x:1)%mod;}
 33 #define MP make_pair
 34 #define FF first
 35 #define SS second
 36 #define LB lower_bound
 37 #define UB upper_bound
 38 #define PB push_back
 39 #define lc ((p<<1)+1)
 40 #define rc ((p<<1)+2)
 41 #define rep(i,a,b) for(int i=a;i<=b;i++)
 42 #define rrep(i,b,a) for(int i=b;i>=a;i--)
 43 #define all(v) (v).begin(),(v).end()
 44 #define clean(v,a) memset(v,a,sizeof(v))
 45 #define get(a) scanf("%d",&a)
 46 #define get2(a,b) scanf("%d%d",&a,&b)
 47 #define get3(a,b,c) scanf("%d%d%d",&a,&b,&c)
 48 
 49 /*
 50  * high precision: printf("%.12lf",(db)ans);
 51  *
 52  * clear output buffer: fflush(stdout);
 53  *
 54  * sync off: ios::sync_with_stdio(false);
 55  *
 56  */
 57 
 58 int m,n;
 59 int dp[2][1<<18];
 60 
 61 class FlippingBitsDiv1
 62 {
 63 public:
 64     int getmin(vector<string> S, int M)
 65     {
 66         string s="";
 67         for(auto v:S)
 68         {
 69             for(int i=0;i<v.size();i++) s+=v[i];
 70         }
 71         m=M;
 72         n=s.length();
 73         for(int i=0;i<n;i++) s[i]-='0';
 74         if(m<=18)
 75         {
 76             clean(dp[1],0);
 77             int all=(1<<m)-1;
 78             rep(i,0,n-1)
 79             {
 80                 clean(dp[i&1],0x3f);
 81                 rep(mask,0,all)
 82                 {
 83                     int id=i%m;
 84                     dp[i&1][mask]=min(dp[i&1][mask],dp[(i&1)^1][mask]+(((mask>>id)&1)^s[i]));
 85                 }
 86                 if((i+1)%m==0)
 87                 {
 88                     rep(mask,0,all)
 89                     {
 90                         dp[i&1][mask]=min(dp[i&1][mask],dp[i&1][mask^all]+1);
 91                     }
 92                 }
 93             }
 94             int ret=0x3f3f3f3f;
 95             rep(mask,0,all)
 96             {
 97                 ret=min(ret,dp[(n-1)&1][mask]);
 98             }
 99             return ret;
100         }
101         else
102         {
103             int block=n/m;
104             int all=(1<<block)-1;
105             int ret=0x3f3f3f3f;
106             rep(mask,0,all)
107             {
108                 int tmp=0;
109                 rep(i,0,block-1)
110                 {
111                     if((mask>>i)&1) tmp++;
112                 }
113                 rep(i,0,m-1)
114                 {
115                     int cnt0=0,cnt1=0;
116                     for(int j=i;j<n;j+=m)
117                     {
118                         int cur=j/m;
119                         cnt0+=(s[j]==0);
120                         cnt1+=(s[j]==1);
121                         if((mask>>cur)&1)
122                         {
123                             swap(cnt0,cnt1);
124                         }
125                     }
126                     tmp+=min(cnt0,cnt1);
127                 }
128                 ret=min(ret,tmp);
129             }
130             return ret;
131         }
132     }
133 };
View Code

 

转载于:https://www.cnblogs.com/ShakuganSky/p/9459262.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值