2020-2021 ACM-ICPC, Asia Seoul Regional Contest

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+(i1)×d))))
可知,最短的时候就是a1在最远的两个 p o s i − ( i − 1 ) × d pos_i -(i-1)\times d posi(i1)×d中间的时候。
逆着的等差数列 a 1 , a 1 − d , a 1 − 2 d . . . a_1,a_1-d,a_1-2d... a1,a1d,a12d...也同理

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值