1. 程式人生 > >【題解】QDUOJ.94.ltwy的位元繃板鍵盤

【題解】QDUOJ.94.ltwy的位元繃板鍵盤

主要考察模擬2進位制的置位和復位,其中有些細節需要注意:

  1. i的範圍是[1,32768],也就是說輸出結果的範圍是[0, 2^32767], 所以只用一個整型變數儲存是不行的,要用陣列模擬大數。
  2. 對於”調皮的操作”,需要考慮的全面一些,諸如:

pRint
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; }