B - Commemorative Dice
签到。暴力枚举
C - Dessert Café
读懂题意就好做了。。(一直没读懂题意所以一直WA)
树。数有多少个点是在两个字母点之间的。
# include <bits/stdc++.h>
# define fo(i,a,b) for(int i=(a);i<=(b);++i)
# define pb push_back
using namespace std;
const int maxn = 1e5+10;
int n,k;
vector<int> g[maxn];
bool kx[maxn]; // 是否是字母
int tag[maxn]; // 子树中字母的个数
set<int> S;
void dfs(int x,int f){
int cnt=0;
for(int i=0;i<g[x].size();++i){
int v=g[x][i];
if(v != f){
dfs(v,x);
tag[x] += tag[v];
if(tag[v]) cnt++;
}
}
if(tag[x]!=k) cnt++;
if(cnt>=2) S.insert(x);
}
int main(){
scanf("%d%d",&n,&k);
fo(i,1,n-1){
int u,v,ww;
scanf("%d%d%d",&u,&v,&ww);
g[u].pb(v);
g[v].pb(u);
}
fo(i,1,k){
int cur;
scanf("%d",&cur);
kx[cur] = tag[cur] = 1;
S.insert(cur);
}
dfs(1,-1);
printf("%d\n",S.size());
return 0;
}
E - Imprecise Computer
构造。
得到了一个D数组,然后要构造两个数组,使得这两个数组合法,且能得到D数组。那么,我们追求一个最优的构造方式,如果连最优的构造方式都无法实现,其他构造肯定更错,则输出no。
这个最优的构造方式就是:从第一位开始,如果是1,说明第一位和第二位有错误,那这个影响要反馈到后一位,我们就让后一位的D-1或者+1。到底是-1还是+1呢?因为要求一个最优的构造方案,我们要尽可能到最后能够消除所有影响,且其间不出现影响为2的情况。所以下一个的D值如果为0,则将其变为1,如果不为0,则将其减去1。到最后一位的时候,如果影响全部消除,就输出yes。如果中途就出现影响为2的情况,这是不正确的,输出no就退出。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e6+4;
int d[maxn];
int main(){
int n;cin>>n;
for(int i=1;i<=n;++i)scanf("%d",&d[i]);
for(int i=1;i<n;++i){
if(d[i]>1) {cout<<"NO"<<endl;return 0;}
if(d[i]) {
if(d[i+1]) d[i+1]--;
else d[i+1]++;
}
}
if(d[n]==0) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
G - Mobile Robot
给robot的初始位置。要求序号毗邻的robot之间距离等于d,且两个robot不能站在同一个位置。求最小的最远移动路径。
最后的位置一定是一个等差数列。可能顺着也可能逆着。
我们要找a1的位置。
那么就是求:
m
i
n
(
m
a
x
i
(
a
b
s
(
p
o
s
i
−
(
a
1
+
(
i
−
1
)
×
d
)
)
)
)
min(max_{i}(abs(pos_i-(a_1+(i-1)\times d))))
min(maxi(abs(posi−(a1+(i−1)×d))))
可知,最短的时候就是a1在最远的两个
p
o
s
i
−
(
i
−
1
)
×
d
pos_i -(i-1)\times d
posi−(i−1)×d中间的时候。
逆着的等差数列
a
1
,
a
1
−
d
,
a
1
−
2
d
.
.
.
a_1,a_1-d,a_1-2d...
a1,a1−d,a1−2d...也同理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000003;
const ll inf = 1e17;
ll r[maxn];
int main(){
int n;ll d;
cin>>n>>d;
ll mx=-inf,mn=inf,mx2=-inf,mn2=inf;
for(int i=1;i<=n;++i){
scanf("%lld",&r[i]);
mx=max(mx,-(i-1)*d+r[i]);
mn=min(mn,-(i-1)*d+r[i]);
mx2=max(mx2,(i-1)*d+r[i]);
mn2=min(mn2,(i-1)*d+r[i]);
}
ll ans1=mx-mn,ans2=mx2-mn2;
ll ans=min(ans1,ans2);
printf("%lld.%d\n",ans/2,(ans%2==0)?0:5);
}
H - Needle
FFT裸题。
我还不会FFT(。
// 代码:david
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
#define N 262145
#define pi acos(-1)
#define E complex<double>
int n,m,L,x,R[N];
E a[N],b[N];
void fft(E *x,int f){
for(int i=0;i<n;i++) if(i<R[i]) swap(x[i],x[R[i]]);
for(int i=1;i<n;i<<=1){
E wn(cos(pi/i),f*sin(pi/i));
for(int p=i<<1,j=0;j<n;j+=p){
E w(1,0);
for(int k=0;k<i;k++,w*=wn){
E y=w*x[i+j+k];
x[i+j+k]=x[j+k]-y;
x[j+k]+=y;
}
}
}
}
const int maxn = 5e4+10;
int nu,nm,nl;
int xu[maxn],xm[maxn],xl[maxn];
int aa[60010],bb[60010];
int main(){
scanf("%d",&nu);
fo(i,1,nu)scanf("%d",xu+i);
scanf("%d",&nm);
fo(i,1,nm)scanf("%d",xm+i);
scanf("%d",&nl);
fo(i,1,nl)scanf("%d",xl+i);
fo(i,1,nu)aa[xu[i]+30000]++;
fo(i,1,nl)bb[xl[i]+30000]++;
int ma=0,mb=0;
fo(i,0,60000){
if(aa[i])ma=i;
a[i]=aa[i];
}
fo(i,0,60000){
if(bb[i])mb=i;
b[i]=bb[i];
}
n=ma+1;
m=mb+1;
m=n+m;
for(n=1;n<=m;n<<=1) ++L;
for(int i=0;i<n;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
fft(a,1),fft(b,1);
for(int i=0;i<n;i++) a[i]=a[i]*b[i];
fft(a,-1);
//for(int i=0;i<=m;i++) printf("%d ",(int)(a[i].real()/n+0.5));
long long ans = 0;
fo(i,1,nm)
ans += (int)(a[xm[i]*2+60000].real()/n+0.5);
printf("%lld\n",ans);
return 0;
}