HDU 4321 Arcane Numbers 2 按位处理, 想法计数题
来源:互联网 发布:淘宝网苹果6手机价格 编辑:程序博客网 时间:2024/06/05 09:06
题目大意:
就是对于给出的A, B, N, A <= 1e4, B <= 1e16, N <= 1e12, 统计在B + A, B + 2*A, B + 3*A, B + 4*A.... B + N*A这N个数的二进制表示法下一共有多少个1
大致思路:
这个题调了好久...想法虽然可行但是写错了几个细节的位置...于是调了半个小时才调过....感觉思路明确了复杂度也就清楚了
思路写在代码注释里了
代码如下:
Result : Accepted Memory : 1620 KB Time : 140 ms
/* * Author: Gatevin * Created Time: 2015/8/11 23:31:36 * File Name: Sakura_Chiyo.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;/* * 首先要求的是B + A, B + 2*A, .... B + N*A这N个数的二进制中总共有多少个1 * 那么我们按位一步一步来, 先统计N个数中第K位是1的个数 * 第K位按照二进制从右向左数, 从1开始数 * 那么不难发现对于第K位B + T*A 和 B + T*A + (1 << K)*A一定是一样的 * 那么我们在计算第K位的时候对于 1 <= T <= (1 << K) - 1计算即可 * 对于B + i*A, 1 <= i <= (1 << K) - 1相同的贡献个数为 (N - i)/(1 << K) + 1个这里是整数除法 * 但是由于K可以比较大, 所以对于第K位不能暴力枚举所有可能的T * 那么当(1 << K) <= A的时候我们暴力枚举 * 当(1 << K) > A时, 我们考虑这样一个事实: * 不难发现如果当前第i项 B + i*A对于(1 << K)取模之后剩下的部分, 在接下来添加A的过程中会有连续的一段不向第K位二进制进位 * 那么就会出现连续的B + i*A, B + (i + 1)*A,...., B + j*A一整段的第K位都是0, 然后又连续一段是1, 两者交替的情况 * 于是这样我们只需要计算连续的一段多长就可以了, 由于(1 << K) > A, 前面一段对(1 << K)取模剩余res的时候接下来一段长度是((1 << K) - res - 1)/A * 那么枚举第K位的时间复杂度是O(log(B + A*N))而每一次枚举, 需要计算区间[1, (1<<K) - 1], 一段区间计算次数是大约是(1<<K)/(((1 << K) - res - 1)/A)次 * 而(1 << K) / (((1 << K) - res - 1)/A)也就是是O(A)的级别 * 于是整体复杂度也就是O(log(B + A*N)*A) */int T;lint A, B, N;lint solve(){ lint ans = 0; lint mx = B + A*N; for(int K = 1; (1LL << (K - 1)) <= mx; K++)//从右向左第K位 { lint L = 1LL << (K - 1); lint S = 1LL << K; lint rest = (B + A) % L; int now = (B + A) & L ? 1 : 0;//当前第K位是0还是1 lint T = 1; while(T <= S && T <= N) { lint step = (L - rest - 1) / A;//接下来会有的连续的now(0 or 1)的个数 step = min(step, min(N - T, S - T)); //也就是说[T, T + step]都是now //一共step + 1个, 对答案的贡献是sigma((N - i) / (1 << K)) T <= i <= T + step //cout<<L<<" "<<rest<<" "<<now<<" "<<T<<" "<<step<<" "<<K<<" "<<ans<<endl; //getchar(); if((N - T) / S + 1 == (N - (T + step))/S + 1) ans += (step + 1)*((N - T)/S + 1) * now; else { lint mid = (N - T) / S * S;//[mid, N - T]这一段都是相同的, [N - (T + step), mid - 1]是相同的 (相同指的是B + (T + (1 << K))*A的个数相同) ans += ((N - T) / S + 1) * (N - T - mid + 1) * now; ans += ((N - (T + step)) / S + 1) * (mid + T + step - N) * now; } rest = (rest + (step + 1)*A) % L; T += step + 1; now = (B + T*A) & L ? 1 : 0;//接下来是相反的连续段 } } return ans;}int main(){ scanf("%d", &T); for(int cas = 1; cas <= T; cas++) { scanf("%I64d %I64d %I64d", &A, &B, &N); printf("Case #%d: %I64d\n", cas, solve()); } return 0;}
0 0
- HDU 4321 Arcane Numbers 2 按位处理, 想法计数题
- hdu - 4320 - Arcane Numbers 1 - 想法题
- hdu - 4321 - Arcane Numbers 2 - 数位统计
- hdu 4320 Arcane Numbers 1
- hdu 4320 Arcane Numbers 1
- HDU - 4320 Arcane Numbers 1
- HDU 4320 Arcane Numbers 1
- HDU 4320 Arcane Numbers 1
- hdu 4320 Arcane Numbers 1(小数进制转化后是否有限位)
- HDU 4320 Arcane Numbers 1 (数论)
- hdu 4320 Arcane Numbers 1 多校联合赛(三)第一题
- HDU 4320 - Arcane Numbers 1 / SWUN 1429 - 进制转化
- HDU 4320 Arcane Numbers 1(12年多校3-数学)
- HDU 2410 Barbara Bennett's Wild Numbers (想法题)
- UVALive 7279 Sheldon Numbers(位运算、暴力、想法)
- HDU 2203 亲和串 (想法题,字符串处理)
- 51nod 1682 中位数计数【想法题】
- hdu 5178想法题
- 黑马程序员——ios学习笔记 OC 分类
- Scala 深入浅出实战经典 第5讲:Scala数组操作实战详解
- hdu1301 prim和kruskal求最小生成树
- 黑马程序员——ios学习笔记 OC Foundation—NSString
- 设计模式:1.2 工厂模式
- HDU 4321 Arcane Numbers 2 按位处理, 想法计数题
- Hibernate缓存非常烦人,想要最新数据连session.clear都不好使
- hdu 3693 Math teacher's homework(数位dp)
- Ray Wenderlich的swift教程02--引用类型和值类型
- 黑马程序员——ios学习笔记 OC Foundation—NSArray&NSDictionary
- !HDU 5371 最长双回文串(多校7)-卡时间-(manacher+排序+set+lower_bound())
- 给出两个年月日,计算出天数差。
- 设计模式:1.3 抽象工厂模式
- 黑马程序员--Java基础--集合(一)