Time Limit: 2000MS | Memory Limit: 262144KB | 64bit IO Format: %I64d & %I64u |
Description
Vasily the bear has got a sequence of positive integers a1, a2, ..., an. Vasily the Bear wants to write out several numbers on a piece of paper so that the beauty of the numbers he wrote out was maximum.
The beauty of the written out numbers b1, b2, ..., bk is such maximum non-negative integer v, that number b1andb2and...andbk is divisible by number 2v without a remainder. If such number v doesn't exist (that is, for any non-negative integer v, number b1andb2and...andbk is divisible by2v without a remainder), the beauty of the written out numbers equals -1.
Tell the bear which numbers he should write out so that the beauty of the written out numbers is maximum. If there are multiple ways to write out the numbers, you need to choose the one where the bear writes out as many numbers as possible.
Here expression xandy means applying the bitwise AND operation to numbers x and y. In programming languages C++ and Java this operation is represented by "&", in Pascal — by "and".
Input
The first line contains integer n (1 ≤ n ≤ 105). The second line contains n space-separated integers a1, a2, ..., an(1 ≤ a1 < a2 < ... < an ≤ 109).
Output
In the first line print a single integer k(k > 0), showing how many numbers to write out. In the second line print k integers b1, b2, ..., bk — the numbers to write out. You are allowed to print numbers b1, b2, ..., bk in any order, but all of them must be distinct. If there are multiple ways to write out the numbers, choose the one with the maximum number of numbers to write out. If there still are multiple ways, you are allowed to print any of them.
Sample Input
5 1 2 3 4 5
2 4 5
3 1 2 4
1 4#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; vector <int> ans; int n; int X[100005]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&X[i]); for(int i=30;i>=0;i--) { ans.clear(); int tmp=-1; for(int j=1;j<=n;j++) { if(X[j]&(1<<i)) { ans.push_back(X[j]); if(tmp==-1)tmp=X[j]; else tmp&=X[j]; } } if(tmp%(1<<i)==0)break; } printf("%d\n%d",ans.size(),ans[0]); for(int i=1;i<ans.size();i++) printf(" %d",ans[i]); puts(""); return 0; }
Description
One beautiful day Vasily the bear painted 2m circles of the same radius R on a coordinate plane. Circles with numbers from 1 to m had centers at points (2R - R, 0), (4R - R, 0), ..., (2Rm - R, 0), respectively. Circles with numbers from m + 1 to 2m had centers at points (2R - R, 2R), (4R - R, 2R), ..., (2Rm - R, 2R), respectively.
Naturally, the bear painted the circles for a simple experiment with a fly. The experiment continued for m2 days. Each day of the experiment got its own unique number from 0 to m2 - 1, inclusive.
On the day number i the following things happened:
- The fly arrived at the coordinate plane at the center of the circle with number
(
is the result of dividing number x by number y, rounded down to an integer).
- The fly went along the coordinate plane to the center of the circle number
(
is the remainder after dividing number x by number y). The bear noticed that the fly went from the center of circle v to the center of circle u along the shortest path with all points lying on the border or inside at least one of the 2m circles. After the fly reached the center of circle u, it flew away in an unknown direction.
Help Vasily, count the average distance the fly went along the coordinate plane during each of these m2 days.
Input
The first line contains two integers m, R (1 ≤ m ≤ 105, 1 ≤ R ≤ 10).
Output
In a single line print a single real number — the answer to the problem. The answer will be considered correct if its absolute or relative error doesn't exceed 10 - 6.
Sample Input
Input1 1Output2.0000000000Input2 2Output5.4142135624观察这 2*m 个圆的圆心坐标不难发现,他们分成了上下两排,同一排相邻的两个圆相切,上下相邻的两个圆相切
再观察 fly 每次运动走的圆的分布规律,不难发现是每次选定一个下面的圆的圆心,分别以上面的圆的圆心为目的点走一次最短路,所以总共有 m2 次运动
那么一个最通常的想法就是:求出这 m2 次运动总共走过的距离
先看看最短路吧:
由于每次一定是一个圆在下面,一个圆在上面,那么可以这样搞:
当两个圆相邻时(列号差为 0),最短路是 2R
当两个圆的列号差为 1 时,最短路是 2R+√2R
当两个圆的列号差为 2 时,最短路是 2R+2√2R
当两个圆的列号差为 3 时,最短路是 4R+2√2R
当两个圆的列号差为 4 时,最短路是 6R+2√2R
当两个圆的列号差为 5 时,最短路是 8R+2√2R
......
将他们存进一个数组 A 中,A[i] 表示列号差为 i 的最短路长度
以 m 为单位,看看每次运动的起始点和终止点
前 m 次运动:起始点始终是下面第 1 个圆,终止点从上面第 1 个圆变化到第 m 个圆
接下来的 m 次运动:起始点始终是下面第 2 个圆,终止点从上面第 1 个圆变化到第 m 个圆
再接下来的 m 次运动:起始点始终是下面第 3 个圆,终止点从上面第 1 个圆变化到第 m 个圆
......
细心的读者在这里的时候估计已经知道该怎么做了,还没想出来的朋友可以接着往下看
从上面可以看出:起始点是在不停的往前走的,而终止点始终是上面的圆从 1 到 m
我们再以 m 为单位,看看他们的距离和
前 m 次运动的距离和我们可以求出来:sum1=∑A[i]
那么接下来的 m 次运动的距离和呢:sum2=sum-A[m-1]+A[1]
再接下来的的 m 次运动的距离和呢:sum3=sum2-A[m-2]+A[2]
第 4 个 m 次运动的距离和:sum4=sum3-A[m-3]+A[3]
......
相信看到这里,大家都知道该怎么做了 o(m) 的扫一遍,用两个指针辅助,这样就可以求出来了
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; const int N=100006; int m; double R, A[N]; void init() { A[0]=2, A[1]=2+sqrt(2); for(int i=2; i<m; i++) A[i]=2*(i-1)+2*sqrt(2); } int main() { scanf("%d%lf", &m, &R); init(); double ans=0; for(int i=0; i<m; i++) { ans+=A[i]; } int p1=1, p2=m-1; double last=ans; for(int i=1; i<m; i++) { last=last-A[p2]+A[p1]; ans+=last; p1++, p2--; } printf("%lf\n", ans/m/m*R); return 0; } B