主要考察模拟2进制的置位和复位,其中有些细节需要注意:
- i的范围是[1,32768],也就是说输出结果的范围是[0, 2^32767], 所以只用一个整型变量存储是不行的,要用数组模拟大数。
- 对于”调皮的操作”,需要考虑的全面一些,诸如:
printf
set 1 1
reset 1i
print 0
都是被当作”调皮的操作”.
主要思路:
预处理,保存2的0~32767次方的值,共32768个值,每个值最多不超过10000位,使用unsigned long long int存储只需要不多于555(粗略)位,sizeof(unsigned long long int) * 555 * 32768未超出要求内存。
记录所有二进制位的情况,要求输出的结果为所有二进制为1的位对应预处理的值的和。
可能有大量print操作,所以计算实时进行,每次set或reset都对结果进行计算。
特别注意处理”调皮的操作”
实现:
//#define gets(buf) gets_s(buf,101)
#include <stdio.h>
#include <string.h>
#define MAX 32768
#define LEN 555
typedef unsigned long long int ull;
ull bits[MAX / sizeof(ull) + 1];//当前值的二进制位记录
ull x[LEN];//当前值
ull z[MAX + 1][LEN] = { 1 };//z[i]为2的i次方
ull Z = 1e18;
void addto(ull * a, ull * b) {
//将a加上b
for (int i = 0; i < LEN; i++) {
a[i] += b[i];
if (a[i] > Z) {
a[i + 1] += a[i] / Z;
a[i] -= Z;
}
}
}
void subto(ull * a, ull * b) {
//将a减去b
for (int i = 0; i < LEN; i++) {
if (a[i] < b[i]) {
a[i] += Z;
a[i + 1] -= 1;
}
a[i] -= b[i];
}
}
void print(ull * x) {
//输出当前值
for (int j = LEN - 1; j >= 0; j--) {
if (x[j]) {
printf("%llu", x[j]);
for (int k = j - 1; k >= 0; k--)
printf("%018llu", x[k]);
puts("");
return;
}
}
puts("0");
}
void init() {
//预处理计算2的0~32767次方
for (int i = 1; i <= MAX; i++) {
addto(z[i], z[i - 1]);
addto(z[i], z[i - 1]);
}
}
int main(void) {
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int i, k, n, m, flag;
char s[4][103], s1[103];
init();
for (; ~scanf("%d\n", &n);) {
memset(bits, 0, sizeof(bits));
memset(x, 0, sizeof(x));
*x = *bits = n;
scanf("%d\n", &m);
for (; m--;) {
gets(s[0]);
/////////////////处理调皮操作////////////////
i = *s[3] = *s[2] = 0;
sscanf(s[0], "%s%s%s", s[1], s[2], s[3]);
if (strcmp(s[1], "print"))
for (; s[2][i]; i++)
if (s[2][i] > '9' || s[2][i] < '0')
break;
if (s[2][i] || *s[3] || (strcmp(s[1], "set") && strcmp(s[1], "reset") && strcmp(s[1], "print")) || (strcmp(s[1], "print") && !*s[2])) {
m++;
puts("Lei shen bie nao, me me da~");
continue;
}
///////////////////////////////////////////
if (*s[0] == 'p') print(x);//输出结果
else {
sscanf(s[2], "%d", &k);
k--;
flag = bits[k / sizeof(ull)] & (1 << k % sizeof(ull));
//flag记录目标位的情况
if (*s[0] == 's') {
bits[k / sizeof(ull)] |= (1 << k % sizeof(ull));//目标位置1
if (!flag) addto(x, z[k]);//如果目标位当前为0,则重新计算结果
}
else if (*s[0] == 'r') {
bits[k / sizeof(ull)] &= ~(1 << k % sizeof(ull));//目标位置0
if (flag) subto(x, z[k]);//如果目标位当前为1,则重新计算结果
}
}
}
}
return 0;
}