A Duplex Printing
#include
using namespace std;
const int N=10;
int n;
int main()
{
cin>>n;
cout<<n/2+n%2<<endl;
}
B Bingo
#include
using namespace std;
const int N=10;
int n,m,a[N][N];
bool vis[N][N];
bool judge()
{
for(int i=1;i<=3;i++)
{
bool flag=true;
for(int j=1;j<=3;j++)
if(!vis[i][j]) flag=false;
if(flag) return flag;
}
for(int j=1;j<=3;j++)
{
bool flag=true;
for(int i=1;i<=3;i++)
if(!vis[i][j]) flag=false;
if(flag) return flag;
}
return vis[1][1]&&vis[2][2]&&vis[3][3]||vis[1][3]&&vis[2][2]&&vis[3][1];
}
int main()
{
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++) scanf("%d",&a[i][j]);
scanf("%d",&n);
while(n--)
{
int x;scanf("%d",&x);
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
if(a[i][j]==x) vis[i][j]=true;
}
if(judge()) printf("Yes\n");
else printf("No\n");
}
C Guess The Number
模拟
#include
using namespace std;
const int N=10;
int n,m,a[N],b[N];
bool judge(int x)
{
int tot=0,s[N];
while(x)
{
s[++tot]=x%10;x/=10;
}
if(tot==0) s[++tot]=0;
if(tot!=n) return false;
reverse(s+1,s+1+tot);
for(int i=1;i<=m;i++)
if(s[a[i]]!=b[i]) return false;
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&a[i],&b[i]);
for(int i=0;i<=999;i++)
if(judge(i))
{
printf("%d\n",i);return 0;
}
printf("-1\n");
}
D Friend Suggestions
并查集(我莫名的写了一个bitset??)。
#include
using namespace std;
const int N=1e5+5;
int n,m,k,f[N],ans[N];
int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
vector<int>v[N],e[N];
bitset<N>b1,b2;
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++)
{
int u,v;scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
u=getf(u);v=getf(v);
if(u==v) continue;
f[u]=v;
}
for(int i=1;i<=k;i++)
{
int u,v;scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=n;i++)
v[getf(i)].push_back(i);
for(int i=1;i<=n;i++)
if(f[i]==i)
{
b1.reset();
for(int u:v[i]) b1[u]=1;
for(int u:v[i])
{
b2.reset();
for(int x:e[u]) b2[x]=1;
b2[u]=1;
b2=~b2;
ans[u]=(b2&b1).count();
}
}
for(int i=1;i<=n;i++)
printf(i==n?"%d\n":"%d ",ans[i]);
}
E Simple String Queries
把 a − z a-z a−z用 0 − 25 0-25 0−25表示,再把他们用二进制位表示,就可以用或运算和线段树单点修改区间查询解决这道问题,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。
#include
using namespace std;
const int N=5e5+5;
int n,q,t[N<<2],lev[N];
char s[N];
void update(int k)
{
t[k]=t[k<<1]|t[k<<1|1];
}
void build(int l,int r,int k)
{
if(l==r)
{
lev[l]=k;
t[k]=1<<(s[l]-'a');return;
}
int m=l+r>>1;
build(l,m,k<<1);build(m+1,r,k<<1|1);
update(k);
}
void fix(int x,char c)
{
if(s[x]==c) return;
s[x]=c;
x=lev[x];
t[x]=1<<(c-'a');
while(x>>=1) update(x);
}
int query(int l,int r,int k,int x,int y)
{
if(r<x||l>y) return 0;
if(l>=x&&r<=y) return t[k];
int m=l+r>>1;
return query(l,m,k<<1,x,y)|query(m+1,r,k<<1|1,x,y);
}
int main()
{
scanf("%d%s",&n,s+1);
build(1,n,1);
scanf("%d",&q);
while(q--)
{
int opt;scanf("%d",&opt);
if(opt==1)
{
int x;char c;
scanf("%d %c",&x,&c);
fix(x,c);
}
else
{
int l,r;scanf("%d%d",&l,&r);
printf("%d\n",__builtin_popcount(query(1,n,1,l,r)));
}
}
}
F - Yakiniku Optimization Problem
首先,容我介绍一下余弦定理,对于三角形三边 a , b , c a,b,c a,b,c,设与每个边相对的角为 A , B , C A,B,C A,B,C,有如下定理(把 c o s cos cos写成 C o s Cos Cos以便于区分):
c 2 = a 2 + b 2 − 2 a b C o s C c^2=a^2+b^2-2abCosC c2=a2+b2−2abCosC
a 2 = b 2 + c 2 − 2 b c C o s A a^2=b^2+c^2-2bcCosA a2=b2+c2−2bcCosA
b 2 = a 2 + c 2 − 2 a c C o s C b^2=a^2+c^2-2acCosC b2=a2+c2−2acCosC
现在,让我介绍一下如何求两个圆的交点,对于两个相交的圆(如下图):
设两个圆的圆心距为 d d d,那么 r 1 , r 2 , d r1,r2,d r1,r2,d以两个圆心和一个交点为顶点构成一个三角形。
再根据上面的定理,我们可以求出角 a a a的大小。
设两个圆的圆心分别为 c 1 , c 2 c1,c2 c1,c2,我们可以用 a t a n 2 atan2 atan2函数求出向量 c 1 − > c 2 c1->c2 c1−>c2与 x x x轴的夹角,设这个夹角为 t t t,那么 r 1 r1 r1这条边的单位向量为 c o s ( t + a ) , s i n ( t + a ) cos(t+a),sin(t+a) cos(t+a),sin(t+a),第一个交点为 c 1 + r 1 ( c o s ( t + a ) , s i n ( t + 2 ) ) c1+r1(cos(t+a),sin(t+2)) c1+r1(cos(t+a),sin(t+2)),那么底下那条边的单位向量为 c o s ( t − a ) , s i n ( t − a ) cos(t-a),sin(t-a) cos(t−a),sin(t−a),同理,两个交点就可以求出来了。
现在,让我们回到这个问题,假设我们的答案是 T T T,答案的端点是 X , Y X,Y X,Y,那么说明有 k k k个点满足 c k s q r t ( d i s ( x k , y k , X , Y ) ) < = T c_ksqrt(dis(x_k,y_k,X,Y))<=T cksqrt(dis(xk,yk,X,Y))<=T,把这个式子移一下 s q r t ( d i s ( x k , y k , X , Y ) ) < = T / c k sqrt(dis(x_k,y_k,X,Y))<=T/c_k sqrt(dis(xk,yk,X,Y))<=T/ck,把两个平方一下,可以发现这是一个圆的方程。
那么问题可以转换为:有 n n n个圆,第 i i i个圆的圆心为 x i , y i x_i,y_i xi,yi,半径为 T / c i T/c_i T/ci,是否存在一片区域,被至少 k k k个点覆盖。显然,这个公共区域一定满足有一个点是两个圆的交点,而答案 T T T具有单调性,所以,我们可以二分答案,再根据以上求圆交的方法,枚举两个圆即可。
时间复杂度 O ( n 4 ) O(n^4) O(n4)(因为我的写法二分的次数和 n n n同阶)。
此外,注意判断一下相离和内含的情况,内含时可以认为公共区域一定时某个圆的圆心。
#include
#define mems(a,x) memset(a,x,sizeof(a))
#define first fi
#define second se
using namespace std;
typedef long long ll;
const int mod=1e9+7,MS=105,N=66;
const double eps=1e-8;
ll inv(ll x){return x==1?x:(mod-mod/x)*inv(mod%x)%mod;}
ll inv(ll x,ll mod){return x==1?x:(mod-mod/x)*inv(mod%x,mod)%mod;}
ll qpow(ll a,ll n){ll ans=1;while(n){if(n&1) ans=ans*a%mod;a=a*a%mod;n>>=1;}return ans;}
ll mul(ll a,ll b){ll ans=0;while(b){if(b&1) ans=(ans+a)%mod;a=(a+a)%mod;b>>=1;};return ans;}
ll qpow(ll a,ll n,ll mod){ll ans=1;while(n){if(n&1) ans=ans*a%mod;a=a*a%mod;n>>=1;}return ans;}
ll mul(ll a,ll b,ll mod){ll ans=0;while(b){if(b&1) ans=(ans+a)%mod;a=(a+a)%mod;b>>=1;};return ans;}
struct vec
{
double x,y;
vec(double x=0,double y=0):x(x),y(y){}
vec operator+(const vec&o)const{ return vec(x+o.x,y+o.y);}
vec operator-(const vec&o)const{ return vec(x-o.x,y-o.y);}
double operator*(const vec&o)const{ return x*o.x+y*o.y;}
double operator^(const vec&o)const{ return x*o.y-y*o.x;}
vec operator/(const double&o)const{ return vec(x/o,y/o);}
vec operator*(const double&o)const{ return vec(x*o,y*o);}
void sc(){scanf("%lf%lf",&x,&y);}
double len(){return sqrt(x*x+y*y);}
};
struct Mat
{
ll a[MS][MS];
int n,m;
Mat(int n=0,int m=0):n(n),m(m) { mems(a,0);}
Mat operator*(const Mat&B)const
{
Mat C(n,B.m);
for(int i=1;i<=n;i++)
for(int j=1;j<=B.m;j++)
for(int k=1;k<=m;k++)
C.a[i][j]=(C.a[i][j]+a[i][k]*B.a[k][j])%mod;
return C;
}
};
int n,k;
vec a[N];
double c[N];
vec s1,s2;
vec polar(double a,double r){return vec(cos(r)*a,sin(r)*a);}
bool intersect(vec c1,vec c2,double r1,double r2)
{
double d=(c1-c2).len();
if(d-eps>r1+r2||d<=r1||d<=r2) return false;
//相离或内含
double a=acos((r1*r1+d*d-r2*r2)/(2*r1*d));
double t=atan2(c2.y-c1.y,c2.x-c1.x);
s1=c1+polar(r1,t-a);
s2=c1+polar(r1,t+a);
return true;
}
bool judge(double T)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(!intersect(a[i],a[j],T/c[i],T/c[j])) continue;
int x=0,y=0;
for(int k=1;k<=n;k++)
{
if(c[k]*(s1-a[k]).len()<=T+eps) x++;
if(c[k]*(s2-a[k]).len()<=T+eps) y++;
}
if(x>=k||y>=k) return true;
}
int x=0;
for(int j=1;j<=n;j++)
if(c[j]*(a[i]-a[j]).len()<=T+eps) x++;
if(x>=k) return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
a[i].sc(),scanf("%lf",&c[i]);
double l=0,r=200000;
for(int i=1;i<=50;i++)
{
double m=(l+r)/2;
if(judge(m)) r=m;
else l=m;
}
printf("%.10f\n",(l+r)/2);
}
/*
|? ?| * |f(x) | == |f(x+1)|
|? ?| |f(x-1)| |f(x) |
f(x)=af(x-1)+bf(x-2)
*/