2017ACM/ICPC广西邀请赛-重现赛1005 CS course
2017-08-31 16:19:30
writer:pprp
这道题快要卡死我了,队友已经告诉我思路了,但是做题速度很缓慢,很费力,想必是因为之前
的训练都是面向题解编程的缘故吧,以后不能这样了,另外这几天要学习一下动态规划,
先普及两个小知识点,这个点很简单很简单但是却卡了我很久很久,
现在作为模板记录下来:
1、将二进制数转化为十进制数
//转化为十进制
//test:ok
ll twoTen(int a[])
{
ll ans = 0;
for(int i = 0 ; i < N ; i++)
{
ans += (1 << i ) * a[i];
}
return ans;
}
2、将十进制数转化为二进制数(bt是一个全局的数组)
//转化为二进制
//test:ok
void tenTwo(int tmp)
{
memset(bt,0,sizeof(bt));
int i = 0;
while(tmp)
{
bt[i++] = tmp%2;
tmp /= 2;
}
}
CS Course
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
Little A has come to college and majored in Computer and Science.
Today he has learned bit-operations in Algorithm Lessons, and he got a problem as homework.
Here is the problem:
You are giving n non-negative integers a1,a2,⋯,an , and some queries.
A query only contains a positive integer p, which means you
are asked to answer the result of bit-operations (and, or, xor) of all the integers except ap .
Today he has learned bit-operations in Algorithm Lessons, and he got a problem as homework.
Here is the problem:
You are giving n non-negative integers a1,a2,⋯,an , and some queries.
A query only contains a positive integer p, which means you
are asked to answer the result of bit-operations (and, or, xor) of all the integers except ap .
Input
There are no more than 15 test cases.
Each test case begins with two positive integers n and p
in a line, indicate the number of positive integers and the number of queries.
2≤n,q≤105
Then n non-negative integers a1,a2,⋯,an follows in a line, 0≤ai≤109 for each i in range[1,n].
After that there are q positive integers p1,p2,⋯,pq in q lines, 1≤pi≤n for each i in range[1,q].
Each test case begins with two positive integers n and p
in a line, indicate the number of positive integers and the number of queries.
2≤n,q≤105
Then n non-negative integers a1,a2,⋯,an follows in a line, 0≤ai≤109 for each i in range[1,n].
After that there are q positive integers p1,p2,⋯,pq in q lines, 1≤pi≤n for each i in range[1,q].
Output
For each query p, output three non-negative integers indicates the result of bit-operations(and, or, xor) of all non-negative integers except ap
in a line.
Sample Input
3 3
1 1 1
1
2
3
Sample Output
1 1 0
1 1 0
1 1 0
题意说明:给你一个个数n,还有查询次数 q
接下来给你n个数(代表这一串数),再给你q个数(代表上一串数的下标+1)
问你当取出第q i 个数的时候,剩下元素的所有的& | xor 运算分别为多少?
思路:构造两个数组,记录某一位0、1的个数,也就是record0和record1数组,
这两个数组用来解决& 和 | 运算,&主要看0的个数,|主要看1的个数
异或比较简单 a xor b xor b = a
用这样的性质来查询剩下的元素的异或值
思路就是这样,但是出现了很多问题
下面贴出代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5; const int N = 40; int arr[maxn]; int bt[N]; //转化为十进制 //test:ok ll twoTen(int a[]) { ll ans = 0; for(int i = 0 ; i < N ; i++) { ans += (1 << i ) * a[i]; } return ans; } //转化为二进制 //test:ok void tenTwo(int tmp) { memset(bt,0,sizeof(bt)); int i = 0; while(tmp) { bt[i++] = tmp%2; tmp /= 2; } } int main() { // freopen("out.txt","r",stdin); ios::sync_with_stdio(false); int record0[N]; int record1[N]; int a, b; int tmp; int ansAnd[N]; int ansOr[N]; while(cin >> a >> b) { memset(ansAnd,0,sizeof(ansAnd)); memset(ansOr,0,sizeof(ansOr)); memset(record0,0,sizeof(record0)); memset(record1,0,sizeof(record1)); memset(bt,0,sizeof(bt)); memset(arr,0,sizeof(arr)); int ansXor = -1; //用来处理对0对1处理的计数 for(int i = 0 ; i < a ; i++) { cin >> tmp; arr[i] = tmp; tenTwo(tmp); //对异或的处理 if(ansXor == -1) ansXor = tmp; else ansXor ^= tmp; //对和还有或的处理 for(int j = 0 ; j < N ; j++) { if(bt[j] == 0) { record0[j]++; } else { record1[j]++; } } } int tmpXor = ansXor; for(int i = 0 ; i < b ; i++) { ansXor = tmpXor; cin >> tmp; //将这个值从记录中取出来--ok tmp = arr[tmp-1]; //先对异或情况进行处理--ok ansXor ^= tmp; //对剩下两种情况进行处理--ok memset(bt,0,sizeof(bt)); tenTwo(tmp); //将对应为的值减去 for(int j = 0 ; j < N ; j++) { if(bt[j] == 0) record0[j]--; else record1[j]--; } //判断或还有和的情况 for(int i = 0 ; i < N ; i++) { if(record0[i] > 0) ansAnd[i] = 0; else ansAnd[i] = 1; if(record1[i] > 0) ansOr[i] = 1; else ansOr[i] = 0; } cout << twoTen(ansAnd) << " " << twoTen(ansOr) << " " << ansXor << endl; for(int j = 0 ; j < N ; j++) { if(bt[j] == 0) record0[j]++; else record1[j]++; } } } return 0; }
总结:
1、这个也是采用每次一调试的办法来做的,但是这次调试中出现了重大失误,由于对以上两个函数调试的不严谨,
判断数据过小,导致小的数据可以过,但是大一点的数据就会失败的情况,这也是这么多次wa的原因
2、还是没有习惯用printf,所以以后写代码就加上fast_io,以后写代码尽量使用带加速到cin函数
3、数据生成器用另外一个project来写,用生成的数据进行对拍,这次发现错误考的就是对拍,没有对拍就很难改下去了,
这道题的对拍比较好些,虽然我用的是别人的代码做的对拍,但是这个对拍很容易写出来,就是运行时间有点长
4、这次还有重大错误就是作用域问题,使用memset的时候要看清作用的范围,还有各种初始化条件,都要关心每一遍的
遍历的作用
5、另外在面对一个循环中的多次询问,要保证每次的询问对下次的询问没有影响,恢复现场才可以。
6、hdu可以用bits/stdc++.h头文件
代码改变世界