【題解】QDUOJ.94.ltwy的位元繃板鍵盤
阿新 • • 發佈:2019-01-09
主要考察模擬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;
}