cf-778B (拆位)

题目

链接 http://codeforces.com/problemset/problem/778/B

Problem Description

Bob recently read about bitwise operations used in computers: AND, OR and XOR. He have studied their properties and invented a new game.

Initially, Bob chooses integer m, bit depth of the game, which means that all numbers in the game will consist of m bits. Then he asks Peter to choose some m-bit number. After that, Bob computes the values of n variables. Each variable is assigned either a constant m-bit number or result of bitwise operation. Operands of the operation may be either variables defined before, or the number, chosen by Peter. After that, Peter’s score equals to the sum of all variable values.

Bob wants to know, what number Peter needs to choose to get the minimum possible score, and what number he needs to choose to get the maximum possible score. In both cases, if there are several ways to get the same score, find the minimum number, which he can choose.

Input

The first line contains two integers n and m, the number of variables and bit depth, respectively (1 ≤ n ≤ 5000; 1 ≤ m ≤ 1000).

The following n lines contain descriptions of the variables. Each line describes exactly one variable. Description has the following format: name of a new variable, space, sign “:=”, space, followed by one of:

Binary number of exactly m bits.
The first operand, space, bitwise operation (“AND”, “OR” or “XOR”), space, the second operand. Each operand is either the name of variable defined before or symbol ‘?’, indicating the number chosen by Peter.

Variable names are strings consisting of lowercase Latin letters with length at most 10. All variable names are different.

Output

In the first line output the minimum number that should be chosen by Peter, to make the sum of all variable values minimum possible, in the second line output the minimum number that should be chosen by Peter, to make the sum of all variable values maximum possible. Both numbers should be printed as m-bit binary numbers.

Sample

inputoutput
3 3
a := 101
b := 011
c := ? XOR b
011
100
5 1
a := 1
bb := 0
cx := ? OR a
d := ? XOR ?
e := d AND bb
0
0


Note

In the first sample if Peter chooses a number 011, then a = 101, b = 011, c = 000, the sum of their values is 8. If he chooses the number 100, then a = 101, b = 011, c = 111, the sum of their values is 15.

分析

  • 题目大概意思是这样:有n个二进制下的m位数,先输入n和m,接下来n行,输入的是每个变量的名称(一个字符串),之后可有两个输入格式:若直接是一个数,那么就代表那个变量的值就是这个数,否则输入一个简单的运算式子(字符串A+运算+字符串B),其中运算只会是“OR”“XOR”以及“AND”,A.B要可能是”?”也可能是一个之前出现过的变量名。所有式子中,”?”代表的是同一个值,我们要求出”?”的两个值,分别使得所有变量的和最大或最小。要是有多个答案,输出字典序最小的。
  • 注意位数不超过 1000,所以说肯定不是用整型来记录,那么就可以考虑拆位,把每一位拆出来单独讨论。
  • 还有,题目所涉及的“与”、“或”、“异或”对每一位的数都只是会影响到那一位上,对其他位上的数没有影响,那么我们只需枚举”?”的每一位(从1到n),看看这一位取什么值(要么是1,要么是0)时,所有变量这一位上的值得和最大或最小,就可以得出答案了。
  • 我用了个map来记录每个变量的名字以及它的编号。

程序

#include <cstdio>
#include <string>
#include <iostream>
#include <map> 
using namespace std;
int n,m,val[5010][1010],f[5010],ans[2][1010];
//f[]   0:直接被赋值 1:and   2:or    3:xor 
string _s,a[5010],b[5010];
map <string , int> name;
int Get(string ss){return name[ss];}

int _check(int x,int y){    //"?" 的第 x 位为 y 时改位所有变量的和
    int Sum=0,k=1,g[5010];
    for (int i=1; i<=n; i++){
        if (f[i]==0) Sum+=g[i]=val[i][x];
        else{
            int k1,k2;
            if (a[i]=="?") k1=y; else k1=g[Get(a[i])];
            if (b[i]=="?") k2=y; else k2=g[Get(b[i])];
            if (f[i]==1) Sum+=g[i]=k1&k2;
            if (f[i]==2) Sum+=g[i]=k1|k2;
            if (f[i]==3) Sum+=g[i]=k1^k2;
        }
    }
    return Sum;
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++){
        cin >>_s; name[_s]=i;
        cin >>_s >>_s;
        if (_s[0]=='0' || _s[0]=='1') for (int j=1; j<=m; j++) val[i][j]=_s[j-1]-'0';
        else{
            a[i]=_s;
            cin >>_s; if (_s=="AND") f[i]=1; else if (_s=="OR") f[i]=2; else f[i]=3;
            cin >>_s; b[i]=_s;
        }
    }
    for (int i=1; i<=m; i++){
        int q1,q2;
        q1=_check(i,1);
        q2=_check(i,0);
        if (q1<q2) ans[0][i]=1,ans[1][i]=0;
        else if (q1>q2) ans[0][i]=0,ans[1][i]=1;
        else ans[0][i]=ans[1][i]=0;
    }
    for (int p=0; p<=1; p++){
        for (int i=1; i<=m; i++) printf("%d",ans[p][i]);
        printf("\n");
    }
}
<think>嗯,用户遇到了Java中将非数字字符串'668f4f2b-20ac-49cb-9c68-f596b3cf99ff'转换为数字时的NumberFormatException问题,想要解决方案。首先,我需要确认这个字符串的格式,看起来像是一个UUID,包含字母和连字符,显然不能直接转换为数字类型。常见的转换方法比如Integer.parseInt()或Long.parseLong()肯定不行,因为它们只能处理数字字符。用户可能想把这个UUID转换成某种数字形式,比如提取其中的数字部分,或者将其哈希为数值。不过UUID本身是128的,通常用两个long来表示,或者转换成BigInteger。这时候需要考虑正确的转换方法,避免使用错误的解析方式。解决方案方面,首先应该检查是否需要转换整个UUID,还是提取其中的数字部分。如果必须处理整个字符串,可以考虑使用UUID类的方法将其转换为数值对象。例如,使用UUID.fromString()解析后,再获取其最高和最低的long值,或者组合成BigInteger。另外,用户可能误用了转换方法,比如试图直接处理包含非数字字符的部分,这时候需要提醒他们进行字符串清理,比如移除连字符和字母,只保留数字部分。但需要注意,这样的处理可能会改变原始数据的含义,尤其是UUID的结构。还要考虑异常处理,建议使用try-catch块来捕获NumberFormatException,并提供有意义的错误提示。同时,可能需要验证输入字符串是否符合预期格式,比如是否是有效的UUID,或者是否包含可转换的数字部分。相关问题部分,需要扩展用户可能遇到的类似问题,例如如何处理其他非数字转换,不同数值类型的转换方法,或者UUID的正确处理方法。这些相关问题可以帮助用户更全面地理解问题,并找到适合他们具体情况的解决方案。</think>### 解决方案 当尝试将包含非数字字符的UUID字符串(如`"668f4f2b-20ac-49cb-9c68-f596b3cf99ff"`)直接转换为数字类型时,Java会抛出`NumberFormatException`,因为UUID中的字母和连字符`-`无法被解析为数字[^1]。以下是具体解决步骤: #### 1. **明确需求** - 若需将UUID整体转换为数值形式: - UUID本质是128二进制值,可分为两个`long`值或组合为`BigInteger` - 示例: ```java UUID uuid = UUID.fromString("668f4f2b-20ac-49cb-9c68-f596b3cf99ff"); BigInteger numericValue = new BigInteger( uuid.toString().replaceAll("-", ""), 16 //以16进制解析去除连字符后的字符串 ); ``` - 若需提取UUID中的数字部分: ```java String numericPart = "668f4f2b-20ac-49cb-9c68-f596b3cf99ff".replaceAll("[^0-9]", ""); long value = Long.parseLong(numericPart); //仅保留纯数字 ``` #### 2. **正确转换方法** ```java //转换为UUID对象后再处理数值 try { UUID uuid = UUID.fromString(inputString); long mostSigBits = uuid.getMostSignificantBits(); //高64 long leastSigBits = uuid.getLeastSignificantBits(); //低64 } catch (IllegalArgumentException e) { //处理非法UUID格式 } ``` #### 3. **防御性编程** ```java //校验是否为合法UUID if (inputString.matches("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")) { //执行转换逻辑 } else { throw new IllegalArgumentException("Invalid UUID format"); } ``` #### 4. **替代方案** - 若需要唯一数值标识符,建议直接生成数字型ID(如`Snowflake ID`)而非UUID - 使用哈希算法(如MD5/SHA-1)生成数值摘要: ```java MessageDigest md = MessageDigest.getInstance("MD5"); byte[] digest = md.digest(uuid.toString().getBytes()); BigInteger hashValue = new BigInteger(1, digest); ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值