1. 程式人生 > 其它 >CF#739-D Make a Power of Two

CF#739-D Make a Power of Two

CF#739-D Make a Power of Two

整局連結:Codeforces Round #739 (Div. 3)

題目大意:

給一個數字,你可以有以下兩種操作:

1.刪除任意數位上的數字;2.在最右邊加上一個數位

問最少經過多少次操作這個數字可以變成2的次方。

思路:

一開始我以為是數位dp直接GG

//以下文字結合程式碼看比較好理解

實際上,只要把給定的數和所有2的次方比較求答案取最小值就行了。當然,2的次方不會是無限個,這題的資料範圍只需要到60次就行。那怎麼去比較呢,可以用子序列的思想。設2的次方是a,給定的是b,我們要找b裡面形如a的子序列(可能不是完整的)。

在b中如果找到不一樣的,就是說要刪掉這個數位。上圖中顏色一樣的就是對應相等的,而b[2]就是應該刪掉的數位。

設指向a的是i,指向b的是j。

當ij指標中有一個走完後,有四種情況:i沒走完,j沒走完,ij都沒走完,ij都走完。

i < la :i沒走完,就是說要b變成a,就要加上a中i後面的那些數字

j < lb :j沒走完,就是說b要變成a,就要減去b中j後面的那些數字

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 2*1e8+10;
string s[70] = {"1","2","4","8","16","32","64","128","256","512","1024","2048","4096","8192","16384","32768","65536","131072","262144","524288","1048576","2097152","4194304","8388608","16777216","33554432","67108864","134217728","268435456","536870912","1073741824","2147483648","4294967296","8589934592","17179869184","34359738368","68719476736","137438953472","274877906944","549755813888","1099511627776","2199023255552","4398046511104","8796093022208","17592186044416","35184372088832","70368744177664","140737488355328","281474976710656","562949953421312","1125899906842624","2251799813685248","4503599627370496","9007199254740992","18014398509481984","36028797018963968","72057594037927936","144115188075855872","288230376151711744","576460752303423488","1152921504606846976"};//這個是1~2**60的打表拿另外一個程式寫很快的。
string t;
int T;

inline ll read(){//快讀
    ll ans = 0;
    char c = getchar();
    while (!isdigit(c))
        c = getchar();
    while (isdigit(c)){
        ans = ans * 10 + c - '0';
        c = getchar();
    }return ans;
}

int solve(string a,string b){
	int i = 0,j = 0,res = 0;
	int la = a.length(),lb = b.length();
	while(i < la && j < lb){
		if(a[i] == b[j])++i,++j;
		else{
			while(j < lb && a[i] != b[j])++j,++res;
		}
	}
	
	if(i < la)res += la - i;//a沒走完,要在最後加數字
	if(j < lb)res += lb - j;//b沒走完,要在最後刪數字
	//cout<<a<<"======================>"<<res<<"\n";
	return res; 
}

int main(){
	T = read();
	while(T--){
		cin>>t;
		int ans = INF;
		for(int i = 0;i < 61; i++)//對和所有2的次方的比較中取最小值
			ans = min(ans,solve(s[i],t));
		cout<<ans<<"\n";
	}
}