ACdreamOJ 1154 Lowbit Sum (数位dp)

ACdreamOJ 1154 Lowbit Sum (数位dp)

ACM

题目地址:ACdreamOJ 1154

题意

 
  1. long long ans = 0;
  2. for(int i = 1; i <= n; i ++)
  3. ans += lowbit(i)

lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然后再转成10进制数。即lowbit(i) = i&(-i)。 
每输入一个n,求ans

分析: 
用二进制去考虑,可以发现这是个数位dp,如果当前第i位为1,说明这个数肯定包含i+1位的全部和,不要忘了第i位也会被求和到。 
额,举个例子:

10->1010, 
第一位是1,所以它肯定包含000~111,也包含1000 
第二位是0,不考虑 
第三位是1,包含0~1,也包含10 
第四位是0,不考虑

所以我们只要算出0~1, 00~11, 000~111...的和就行了 
列出1~15的二进制码,发现,最后一个1在最后一位有一半,在倒数第二位的有1/4,所以根据这个规律打表就行了。

代码

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        1154.cpp
*  Create Date: 2014-07-31 08:46:56
*  Descripton:  aoj 1154
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;

const int N = 30;

ll n;
ll dp[N];

// table
void init() {
	repf (i, 1, N - 1) {
		ll ans = 0, t = (1<<i), v = 1;
		while (t) {
			ans += (t>>1) * v;	// there was (t>>1) numbers whose last 1 is in log2(v)
			v <<= 1;
			t >>= 1;
		}
		dp[i] = ans;
//		cout << ans << ' ';
	}
}

ll solve(ll n) {
	int i = 0;
	ll ret = 0;
	while (n) {
		if (n & 1)
			ret += dp[i] + (1<<i);		// don't forget there must be a 1<<i
		n >>= 1;
		i++;
	}
	return ret;
}

// brute force
ll bf(ll n) {
	ll ans = 0;
	repf (i, 1, n)
		ans += i&(-i);
	return ans;
}

int main() {

	init();

	while (cin >> n) {
		cout << solve(n) << endl;
//		cout << n << ' ' << solve(n) << ' ' << bf(n) << endl;
	}
	return 0;
}


2025年CCF非专业级别软件能力认证第一轮模拟测 试 (CSP-J1)入门级 C++ 语言试题 认证时间:2024年9月21日09:30-11:30 一、单项选择题(共15题,每题2分,共计30分) 1. 以下哪一项不属于内存(D) A. RAM B. ROM C. Cache D. DOS 2. 下列四种不同进制的数中,与其他三项不同的是(D) A. (11111101001)2 B. (5622)7 C. (BCA)13 D. (13231)6 3. 现在有一个存有2048 × 1024 像素的黑白图像,请问需要多大存储空间?B A. 512KB B. 256KB C. 2MB D. 1MB 4. 5个男生,3个女生围成一圈,要求女生之间互不相邻,求有多少种方案?A A. 1440 B. 7200 C. 576 D. 2880 5. 中国计算机学会于( B )年创办全国青少年计算机程序设计竞赛。 A. 1983 B. 1984 C. 1985 D. 1986 6. 现在有序列 “7,4,5,2,3” 若使用冒泡排序获得其单调递增序列,需要进行多少次交换操作? A. 6 B. 7 C. 8 D. 9 7. 二叉树的前序遍历为 “1,2,3,4,5,6,7,8,9”,中序遍历为 “3,2,5,4,6,1,7,9,8”,则后序遍历为() A. “3,5,6,4,2,9,8,7,1” B. “4,5,6,3,2,9,8,7,1” C. “4,5,6,3,2,9,7,8,1” D. “4,6,5,3,2,9,7,8,1” 8. 能找出欧拉回路的无向图可能不具有的性质有() A. 所有点的度数都为偶数 B. 图中的所有点互相连通 C. 图中包含的边数为偶数 D. 一定能找到一条欧拉路 9. 以下哪项不是C++语言的关键字() A. goto B. do C. caseI D. cin 10. 2025以内,与2025互质的数有多少个?() A. 1080 B. 1024 C. 1001 D. 945 11. 16 位 unsigned short int 的数据范围是() A. 0~32767 B. 0~32768 C. 0~65535 D. 0~65536 12. (3+(7-2)*5-6)/2 的后缀表达式为() A. 3 7 2 - 5 * 6 - + 2 / B. 3 7 + 2 - 5 * 6 - 2 / C. 3 7 2 - 5 * 6 + - 2 / D. 6 7 2 - 5 * 3 + - 2 / 13. 73 的格雷码为() A. 1010101 B. 1001001 C. 1101101 D. 0110110 14. 下列语言中使用解释器将源代码转为机器代码的语言为() A. C# B. JavaScript C. Java D. C++ 15. 在使用快速幂算法时,计算2^23时需要使用多少次乘法() A. 6 B. 7 C. 8 D. 22 二、 阅读程序(程序输入不超过数组成字符串定义的范围:判断题正确填"T",错误填"F";除特殊说明外,判断题1.5 分,选择题3分,共计40分) 程序一 16. 第 行中 函数若传入的 则可能导致编译错误() 17. tree[i] 表示 a[i]~a[i+lowbit(i)] 的和() 18. ask(i) 求解的是 a[1]~a[i] 的和 () #include<iostream> using namespace std; const int NN = 1e5; int n; int a[NN]; int tree[NN]; int lowbit(int x){return x & (-x);} void add(int pos,int num){ while(pos<= n){ tree[pos] += num; pos += lowbit(pos); } } int ask(int pos){ int ans = 0; while(pos){ ans += tree[pos]; pos -= lowbit(pos); } return ans; } int main(){ cin >> n; for(int i = 1; i <= n; ++i) cin >> a[i]; for(int i = 1; i <= n; ++i) add(i,a[i]); int m; cin >> m; for(int i = 1,pos,num; i <= m; ++i){ cin >> pos >> num; a[pos] += num; add(pos,num); } int query; cin >> query; while(query--){ int l,r; cin >> l >> r; cout << ask(r) - ask(l-1) << endl; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 19. 当输入如下时,输出为() A. 13 B. 16 C. 17 D. 20 20. 程序第 行,若将 query++ 换为 `++query 对于程序(输入合法)的影响为() A. 能得到所有正确的输出,但是输入结束后程序未能正常结束 B. 只能得到部分输出,且输出的答案并非完全正确 C. 能得到所有正确的输出,且输入结束后程序正常结束 D. 只能得到部分输出,但输出的答案完全正确 程序二 21. 当输入的字符串为 AC{[3FUN}]% 时程序的输出为 AC{FUNFUNFUN} () 22. (2分)程序的输出一定不包含 “%” 和 “ ”(空格)() 5 3 1 2 4 6 1 1 3 2 4 1 2 5 1 2 3 4 5 6 7 #include<iostream> #include<string> using namespace std; string encode(){ int num; char ch; string ans = "", ori = ""; while(cin >> ch && ch != '%'){ if(ch == '['){ cin >> num; ori = encode(); while(num--) ans += ori; } else if(ch == ']') return ans; else ans += ch; } return ans; } int main(){ cout << encode(); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 23. 将第 行替换为 while(ch != '%' && cin >> ch){ 对程序答案的输出没有影响() 24. 当输入的字符串为 AC[3 2%[2 FUN]%HAPPY 时,输出为() A. AC222FUNFUN B. AC2FUNFUN2FUNFUN2FUNFUN C. AC222FUNFUNHAPPY D. AC2FUNFUN2FUNFUN2FUNFUNHAPPY 25. (4分)当输入的字符串为 AC[3 2 3 %[4 [2% 3 2 FUN]% 时,输出为() A. AC23232332FUN32FUN32FUN32FUN B. AC2 3 2 3 2 3 2 FUN2 FUN2 FUN2 FUN C. AC2 3 2 3 2 3 2 3 2 FUN 3 2 FUN 3 2 FUN 3 2 FUN D. AC2323232FUN2FUN2FUN2FUN 26. 若将 encode 函数所有的返回语句都改为 return ori + ans + ori 则输入 AC[3FUN]% 得到的输出为() A. ACFUNFUNFUNFUNFUN B. FUNACFUNFUNFUNFUN C. FUNFUNACFUNFUNFUN D. FUNFUNFUNACFUNFUN 程序三 #include<iostream> using namespace std; int n,a[500010],c[500010]; long long ans; void merge_sort(int left,int right) { if(left == right) return; int mid = (left + right) / 2, i = left, j = mid+1, k = left; merge_sort(left,mid); merge_sort(mid+1,right); while(i <= mid && j <= right) if(a[i] <= a[j]) c[k++] = a[i++]; else c[k++] = a[j++], ans += mid-i; while(i <= mid) c[k++] = a[i++]; while(j <= right) c[k++] = a[j++]; for(int i = left; i <= right; i++) a[i] = c[i]; } int main(){ cin >> n; for(int i = 1; i <= n; i++) cin >> a[i]; merge_sort(1,n); cout << ans; return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 27. 若将第 行 的赋值改为 mid = left + (right-left)/2.0 ,对程序无影响( ) 28. 该程序总是输出非负整数() 29. 该程序用于求解逆序对个数() 30. 若输入 5 2 4 3 1 3 则程序输出为() A. 2 B. 4 C. 5 D. 10 31. (4分)若将第 行的 ans += mid - i 改为 ans += right - i - mid + 2 并输入 5 2 4 3 1 3 则程序 输出为() A. 2 B. 4 C. 5 D. 10 32. 若 , 则程序可能输出的答案的最大值为() A. 12 B. 15 C.18 D. 21 三、完善程序(单选题,每小题 分,共计 分) 1 立方根求解 问题:给一浮点数 ,输出其立方根(保留5位小数) 33. ①处应填() A. 1e5 B. 1e-5 C. 1e-6 D. 1e-7 34. ②处应填() A. right - left > eps B. right - left > -eps C. left - right > eps D. left - right > -eps 35. ③处应填() A. left = mid B. right = mid C. left = mid + eps D. right = mid - eps 36. ④处应填() A. left = mid B. right = mid C. left = mid + eps D. right = mid - eps #include<cstdio> using namespace std; const double eps = ①; int main(){ double a; double left = -1000.0,right = 1000.0,mid; scanf("%lf",&a); while(){ mid = left + (right - left) / 2; if(mid * mid < a / mid) ③; else ④; } printf("⑤",mid); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 37. ⑤处应填() A. %5.lf B. %.5lf C. %6.lf D. %.6lf 2 石子合并 给一排 堆石子,每堆石子的质量为 ,每次合并操作代价为两堆石子质量之和,求将所有石子堆合并为一个大石堆 所需要的最小代价 38. ①处应填() A. sum_pre[i+1] = sum_pre[i] + a[i+1] B. sum_pre[i+1] = sum_pre[i] + a[i] C. sum_pre[i] = sum_pre[i-1] + a[i-1] D. sum_pre[i] = sum_pre[i-1] + a[i] 39. ②处应填() A. 0 B. 1 C. 2 D. 3 40. ③处应填() A. i + len B. i + len - 1 C. n - i - len D. n - i - len + 1 41. ④处应填() A. dp[i][k-1] + dp[k][j] + sum_pre[j] - sum_pre[i] B. dp[i][k-1] + dp[k][j] + sum_pre[j] - sum_pre[i-1] C. dp[i][k] + dp[k+1][j] + sum_pre[j] - sum_pre[i] D. dp[i][k] + dp[k+1][j] + sum_pre[j] - sum_pre[i-1] 42. ⑤处应填() A. dp[1][1] B. dp[n][n] C. dp[1][n] D. dp[1][1] + dp[1][n] + dp[n][n] #include<iostream> using namespace std; int n,a[310],sum_pre[310],dp[310][310]; int main() { cin >> n; memset(dp,0x3f,sizeof(dp)); for(int i = 1; i <= n; i++) { cin >> a[i]; ①; ②; } for(int len = ③; len <= n; len++) { for(int i = 1; i <= n-len+1; i++) { int j = ③; for(int k = i; k < j; k++) dp[i][j] = min(dp[i][j], ④); } } cout << dp[1][n]; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
最新发布
07-25
### 模拟试题设计:2025年CCF CSP-J1入门级C++语言考试 以下是一组模拟试题,涵盖选择题、阅读程序题和程序填空题,每道题后附有答案解析。 --- ### 一、选择题 #### 1. 下列关于C++中`const`关键字的描述,哪一个是正确的? A. `const`只能用于定义常量,不能用于函数参数 B. `const`可以修饰类的成员函数,表示该函数不会修改类的数据成员 C. `const`变量可以在程序运行时被修改 D. `const`只能用于基本数据类型,不能用于自定义类型 **答案:B** `const`关键字可以用于类的成员函数,表示该函数不会修改类的数据成员。这是C++中常量成员函数的重要特性。 --- #### 2. 以下哪种数据结构适合实现“先进先出”(FIFO)的队列操作? A. 栈 B. 队列 C. 堆 D. 链表 **答案:B** 队列(`std::queue`)是专门用于实现先进先出的数据结构。 --- ### 二、阅读程序题 #### 3. 阅读下列程序,判断其输出结果。 ```cpp #include <iostream> using namespace std; int main() { int a = 5, b = 3, c = 0; c = (a > b) ? a : b; cout << c << endl; return 0; } ``` **输出结果:5** 三元运算符 `(a > b) ? a : b` 表示如果 `a > b` 成立,则返回 `a`,否则返回 `b`。由于 `5 > 3` 成立,因此 `c = 5`。 --- #### 4. 阅读下列程序,判断其输出结果。 ```cpp #include <iostream> using namespace std; int main() { int arr[] = {1, 2, 3, 4, 5}; int *p = arr; cout << *(p + 2) << endl; return 0; } ``` **输出结果:3** 指针 `p` 指向数组 `arr` 的第一个元素,`*(p + 2)` 表示访问第三个元素,即 `arr[2]`,值为 3。 --- ### 三、程序填空题 #### 5. 以下程序用于计算1到n的累加和,请填写缺失的代码。 ```cpp #include <iostream> using namespace std; int main() { int n, sum = 0; cin >> n; for (int i = 1; i <= n; i++) { sum += i; } cout << sum << endl; return 0; } ``` **解析:** 在`for`循环中,每次将`i`加到`sum`中,最终输出累加和。 --- #### 6. 以下程序用于判断一个数是否为素数,请填写缺失的代码。 ```cpp #include <iostream> using namespace std; bool is_prime(int n) { if (n <= 1) return false; for (int i = 2; i * i <= n; i++) { if (n % i == 0) return false; } return true; } int main() { int n; cin >> n; if (is_prime(n)) cout << "Yes" << endl; else cout << "No" << endl; return 0; } ``` **解析:** 在`is_prime`函数中,通过遍历从2到`sqrt(n)`的整数,判断是否存在能整除`n`的因子。若存在,则`n`不是素数;否则为素数。 --- ### 四、综合编程题 #### 7. 编写一个程序,输入一个字符串,统计其中每个字母(不区分大小写)出现的次数,并按字母顺序输出。 示例输入: ``` Hello World ``` 示例输出: ``` d:1 e:1 h:1 l:3 o:2 r:1 w:1 ``` **参考代码:** ```cpp #include <iostream> #include <string> #include <map> #include <cctype> using namespace std; int main() { string s; getline(cin, s); map<char, int> freq; for (char c : s) { if (isalpha(c)) { c = tolower(c); freq[c]++; } } for (auto it = freq.begin(); it != freq.end(); ++it) { cout << it->first << ":" << it->second << endl; } return 0; } ``` **解析:** 使用`map<char, int>`存储每个字母的频率,遍历字符串时忽略非字母字符,并将大写字母转换为小写进行统一统计,最后按字母顺序输出。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值