D*Dr. Evil Underscores
题意:给n个数,找一个数X使maxi=1到n(X xor ai)最小
思路:具体思路就是分治,在二进制中,对于a1∼an,如果该位上全是0或1,则该位填相反值就可以抵消掉进入下一位了。如果在该位上既有1又有0,说明这一位上的数是躲不掉的,那么这一位填0则该位是1的数结果+2^ i、填1则该位是0的数结果+2^ i ,所以在返回的数里加一个1<<i,而对于后面的数则取最小值即可min(dfs(i-1, v0), dfs(i-1, v1) )+(1 << i)
(要注意的一点:i 要一直算到i<0才结束,因为当i==0是运算的是最后一位的值)
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
using namespace std;
#define Inf 0x7fffffff
typedef long long ll;
const int N=100007;
int n,a[N];
int dfs(int i,vector<int> &v){
vector<int>v0,v1;
if(i<0)return 0;
for(auto &j:v){ //类似于迭代器遍历容器内部元素
if((j>>i)&1)v1.push_back(j);
else v0.push_back(j);
}
if(v0.size()==0)return dfs(i-1,v1);
if(v1.size()==0)return dfs(i-1,v0);
return min(dfs(i-1,v0),dfs(i-1,v1))+(1<<i);
//第i位上填1的话,本位上为0的数的结果都要+2^i
//第i位上填0的话,本位上为1的数的结果都要+2^i
//所以两种情况都要在返回值里加上(1<<i)
}
vector<int>v;
int main(){
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]),v.push_back(a[i]);
cout<<dfs(30,v);
}
H*Rolling The Polygon
题意:顺时针给处凸n边形的顶点坐标p0,p1…pn-1,与其内一点Q的坐标,让多边形沿直线滚动一圈,求点Q的轨迹长度。
思路:因为点Q随着凸n边形整体滚动,所以不需要求旋转后的坐标,第i次翻滚之前,点Q到右下方顶点(即旋转点) 的距离等于最初点Q到第i顶点的距离,然后用余弦定理和arccos求出旋转角,弧长=αr
#include<bits/stdc++.h>
int n,t,cnt;
double x[100],y[100],ans,xq,yq;
double dis(double x,double y,double xx,double yy){
return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++)scanf("%lf%lf",&x[i],&y[i]);
x[n]=x[0];y[n]=y[0];x[n+1]=x[1];y[n+1]=y[1];
ans=0;
scanf("%lf%lf",&xq,&yq);
for(int i=0;i<n;i++){
double r=dis(xq,yq,x[i+1],y[i+1]);
double cosC=(dis(x[i],y[i],x[i+1],y[i+1])*dis(x[i],y[i],x[i+1],y[i+1])+
dis(x[i+1],y[i+1],x[i+2],y[i+2])*dis(x[i+1],y[i+1],x[i+2],y[i+2])-
dis(x[i],y[i],x[i+2],y[i+2])*dis(x[i],y[i],x[i+2],y[i+2]))/(2*
dis(x[i],y[i],x[i+1],y[i+1])*dis(x[i+1],y[i+1],x[i+2],y[i+2]));
//余弦定理cosC=(a^2+b^2-c^2)/2ab
double C=acos(-1)-acos(cosC); //acos(-1)是PI=3.1415926...
ans+=C*r;
}
printf("Case #%d: %.3lf\n",++cnt,ans);
}
}