标签:http io ar for 数据 sp 代码 on c
题目大意:给出N个数,然后问里面有多少个子串,对于每个子串做或运算的结果小于m。
解题思路:这题测试数据比较水,暴力就可以过。正解:把每个数都用二进制存起来,然后一开始head和tail都指向1.每次tail都++,对于每个tail求出离他最远的head。然后求和一下每个tail满足条件的子串。注意当head到tail的和超过m的时候,就要将head往后移动,这个时候就要将head的数字对应有1的位置--。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1e5 + 5; int n; int num[maxn], m; int Num[maxn][35], cnt[35]; int t[35]; void init () { t[0] = 1; for (int i = 1; i <= 30; i++) t[i] = t[i - 1] * 2; } bool judge () { ll Sum = 0; for (int i = 0; i <= 30; i++) if (cnt[i]) Sum += t[i]; if (Sum < m) return true; return false; } ll solve () { ll ans = 0; for (int k = 1; k <= n; k++) { for (int i = 30; i >= 0; i--) { if (num[k] >= t[i]) { Num[k][i] = 1; num[k] -= t[i]; } else Num[k][i] = 0; } } int head, tail; head = tail = 1; for (int i = 0; i <= 30; i++) cnt[i] = 0; ll tmp; while (tail <= n) { for (int i = 0; i <= 30; i++) if (Num[tail][i]) cnt[i]++; if (!judge()) { while (head <= tail && !judge()) {//注意head移动的边界 for (int i = 0; i <= 30; i++) if (Num[head][i]) cnt[i]--; head++; } } ans += tail - head + 1; tail++; } return ans; } int main () { int T; scanf ("%d", &T); init(); for (int cas = 1; cas <= T; cas++) { printf ("Case #%d: ", cas); scanf ("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf ("%d", &num[i]); printf ("%I64d\n", solve()); } return 0; }
标签:http io ar for 数据 sp 代码 on c
原文地址:http://blog.csdn.net/u012997373/article/details/39153441