简单的爱心效果

切蛋糕

题目描述

有一个蛋糕,它是由长度是L的二进制组成的。现在需要把蛋糕切K-1刀,这样蛋糕就会被切成K份,每一份蛋糕其实就是一段连续的二进制,而且每一份蛋糕的二进制不能有前导0。小LW今年5岁了,所以她希望把每一份蛋糕的二进制转为十进制之后,都是5的幂,即可以表示成5^X,其中X是整数。求满足题意的最小的正整数K。如果无法完成任务,输出-1。

输入格式 

多组测试数据。
第一行,一个整数R,表示有R组测试数据。 1 <= R <= 25。
每组测试数据格式如下:
     第一行,一个整数L。 1 <= L <= 50。
     第二行,L个二进制数字,0或者1。

输出格式

共R行,每行一个整数。

输入/输出例子1

输入:

11
9
101101101
7
1111101
5
00000
9
110011011
10
1000101011
27
111011100110101100101110111
49
1101100011010111001001101011011100010111011110101
4
0101
4
1001
50
11111111111111111111111111111111111111111111111111
14
10111001110011

输出:

3
1
-1
3
-1
5
1
-1
-1
50
4

样例解释

题目来源

切蛋糕(第4题)

思路

详细的地方看注释吧o(╥﹏╥)o,这道题感觉自己暴力了一波,但是为什么题目发布者把它放进递推里面。。。

这里大致说一下:

首先为了省一些时间,直接就打了一个5的n次幂的二进制串,注意任何非零数的0次幂等于1!

#include<iostream>
using namespace std;
int main(){
    for(int i=0;i<=23;i++){
        long long temp=1;
        for(int j=1;j<=i;j++) temp*=5;//pow(5,i)
        bool a[100]={};
        int len=1;
        while(temp!=0){
            a[len++]=temp&1;//或temp%2 
            temp>>=1;//或temp/=2 
        } 
        for(int j=len-1;j>=1;j--) cout<<a[j];
        cout<<'\n';
    }
    return 0;
} 

然后你要做的就是从左往右找,假如第一刀都切不上去,那自然就可以返回ERROR了,可以的话先切一刀,剩下的字符串再继续递归,可能出现多种情况,所以要扫一遍取ans。

然后输出最后的答案。。。(允许我水一行字数)

然后就没了。

完整代码

#include<iostream>
#include<cstring>
#define ERROR 100000000
using namespace std;
string s[25];
int f(string temp){//递归代码,注意理解 
    if(temp.size()==0) return 0;//如果字符串长度为0,就是字符串已经切完,返回0 
    if(temp[0]=='0') return ERROR;//切出来的二进制串不能有前缀0,返回ERROR 
    int ans=ERROR;//因为后面取最小值,开局取最大ERROR 
    for(int i=1;i<=23;i++){
        //遍历每一个可能切成的值为5次幂的二进制串
        if(temp.size()>=s[i].size()&&temp.substr(0,s[i].size())==s[i]){
            //判断是否可以切出这样的一段
            int tmp=f(temp.substr(s[i].size(),temp.size()-s[i].size()));
            //继续往下切二进制串 
            //如果切到最后发现不可行也会返回ERROR,一直递归回来,所以可以放心写 
            if(tmp==ERROR) continue;
            //不能切直接跳过,避免出现可能的BUG 
            ans=min(ans,tmp+1);
            //要找的是切成的最少份数 
        }
    }
    return ans;//返回答案
    /*
        或者也可以写成这样:  
        return ans==ERROR?-1:ans;
        这样ask()函数里就不用再判断 
    */ 
}
inline void pow_5_n(){//s[i]等于pow(5,i)的二进制串,为了节省时间,可以提前打表 
    s[1]="1";//注意1=pow(5,0) 
    s[2]="101";
    s[3]="11001";
    s[4]="1111101";
    s[5]="1001110001";
    s[6]="110000110101";
    s[7]="11110100001001";
    s[8]="10011000100101101";
    s[9]="1011111010111100001";
    s[10]="111011100110101100101";
    s[11]="100101010000001011111001";
    s[12]="10111010010000111011011101";
    s[13]="1110100011010100101001010001";
    s[14]="1001000110000100111001110010101";
    s[15]="101101011110011000100000111101001";
    s[16]="11100011010111111010100100110001101";
    s[17]="10001110000110111100100110111111000001";
    s[18]="1011000110100010101111000010111011000101";
    s[19]="110111100000101101101011001110100111011001";
    s[20]="100010101100011100100011000001001000100111101";
    s[21]="10101101011110001110101111000101101011000110001";
    s[22]="1101100011010111001001101011011100010111011110101";
    s[23]="1000011110000110011110000011001001101110101011001001";
    //pow(5,23)>pow(2,50),取到5的23次幂就够了 
}
inline void ask(){
    int len;
    string str;
    cin>>len;//依据样例输入长度,虽然用不上
    cin>>str;
    int rans=f(str);
    if(rans==ERROR) cout<<-1<<'\n';//依题意,无法完成任务输出-1 
    else cout<<rans<<'\n';
}
int main(){
    pow_5_n();//预处理
    int r;
    cin>>r;//样例数量 
    while(r--) ask();
    return 0;
}

 

 

posted @ 2023-04-20 19:00  Light-Chaser  阅读(38)  评论(0编辑  收藏  举报
简单的爱心效果