zoukankan      html  css  js  c++  java
  • 2020-2021 ACM-ICPC, Asia Seoul Regional Contest

    Solved:

    • B、Commemorative Dice
    • C、Dessert Café
    • E、Imprecise Computer
    • G、Mobile Robot
    • H、Needle

    B、Commemorative Dice

    签到

    int gcd(int a,int b)
    {
        if(b == 0)return a;
        return gcd(b,a%b);
    }
    int main()
    {
        int a[10],b[10];
        for(int i=1;i<=6;i++)scanf("%d",&a[i]);
        for(int i=1;i<=6;i++)scanf("%d",&b[i]);
        int sum=0;
        for(int i=1;i<=6;i++){
            for(int j=1;j<=6;j++){
                if(a[i]>b[j])sum++;
            }
        }
        int num=gcd(sum,36);
        printf("%d/%d",sum/num,36/num);
    }
    

    C、Dessert Café

    题意:
    题目给出一棵树,树上有一些结点是特殊点,问在这些特殊点之间的路径上(包括特殊点在内)一共有多少个结点。

    想法:
    考虑对整棵树进行 (DFS) ,从一个点开始,去求这个结点的子树中拥有特殊点的个数,如果某个点的子树中特殊点的个数在 (2sim (k-1)) 之间,那么这个点就在特殊点的之间的路径上。

    代码:

    int n,k;
    vector<int>mp[maxn];
    int num[maxn]; 
    bool isA[maxn];
    int ans=0;
    void dfs(int u,int f)
    {
    	int cnt=0;
    	for(int i=0;i<mp[u].size();i++)
    	{
    		int v=mp[u][i];
    		if(v!=f)
    		{
    			dfs(v,u);
    			num[u]+=num[v];
    			if(num[v]) cnt++;
    		}
    	}
    	if(num[u]!=k) cnt++;
    	//dbg(u);
    	if(cnt>=2&&!isA[u])  ans++;
    	//dbg(ans);
    }
    void run()
    {
    	n=rd();
    	k=rd();
    	for(int i =1;i<n;i++)
    	{
    		int u=rd(),v=rd(),w=rd();
    		mp[u].push_back(v);
    		mp[v].push_back(u);
    	}
    	for(int i=0;i<k;i++)
    	{
    		int x=rd();
    		num[x]=1;
    		isA[x]=true;
    		ans++;
    		//cout<<ans<<" sss"<<endl;
    	}
    	dfs(1,-1);
    	cout<<ans<<endl;
    }
    signed main()
    {	
    	run();
    	return 0;
    }
    

    E、Imprecise Computer

    队友tql

    int n,k;
    int dp[maxn];
    void run()
    {
    	n=rd();
    	for(int i=1;i<=n;i++) dp[i]=rd();
    	bool flag=1;
    	for(int i=1;i<=n;i++)
    	{
    		if(dp[i]>=2) {
    			flag=0;
    			break ; 
    		}
    		else{
    			if(dp[i]) {
    				if(dp[i+1]) dp[i+1]--;
    				else dp[i+1]++;
     			}
    		}
    	}
    	puts((flag&&dp[n]==0)?"YES":"NO");
    }
    signed main()
    {	
    	run();
    	return 0;
    }
    

    G、Mobile Robot

    题意:
    (n) 个机器人,编号从 (1 sim n),告诉你每个机器人在坐标轴上的位置,问通过对每个机器人的移动,让编号 (i 和 i-1)号机器人($iin left[ 2,n ight] $)的距离保持在 (d),问所有机器人中移动距离的最大值的最小值是多少。

    想法:
    首先为了达到题目要求,就必须让每个机器人在坐标轴上的排列从 (1sim n),或者是 (nsim 1),只有这样才能是满足题目条件的。在此条件的基础上,我们去考虑移动的距离问题。因为在坐标轴上,我们的操作就是把 (1sim n)编号的机器人移动每个指定点即可,而这个指定点是只要确定一个,就可以确定全部。我们可以设指定点为 (x+d、x+2 imes d、x+3 imes d......),那么我们就可以求出每个点移动的距离,然后可以求出带未知数 (x) 的最大移动值 (maxn) 和最小移动值 (minn)。然后我们考虑怎么让最大值的最小,并且最大值还是最大,很显然,我们可以通过 (maxn-minn) 求出最大值的最小值,而在减的过程中,x也减掉了。从而得到答案。需要注意,还需要考虑 (nsim 1)排列,即把机器人的编号反过来即可。

    代码:

    ll a[maxn],b[maxn];
     
    int main()
    {
        ll n,m;
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            b[n-i+1]=a[i];
        }
        ll maxx=-INF,minx=INF;
        for(int i=1;i<=n;i++){
            maxx=max(maxx,a[i]-1ll*i*m);
            minx=min(minx,a[i]-1ll*i*m);
        }
        ll ans=maxx-minx;
        maxx=-INF,minx=INF;
        for(int i=1;i<=n;i++){
            maxx=max(maxx,b[i]-1ll*i*m);
            minx=min(minx,b[i]-1ll*i*m);
        }
        ans=min(ans,maxx-minx);
        if(ans%2==1){
            printf("%lld.5",ans/2);
        }else{
            printf("%lld.0",ans/2);
        }
    }
    

    H、Needle

    题意:
    给你三个数组 (a、b、c),问在这些数组中存在多少组 ((i,j,k)) 满足 (a[i]+c[k]=2 imes b[j])

    想法:

    • (n) 很大,暴力肯定会超时。考虑多项式乘法,把数组 (a,b) 各自作为两个多项式中 (x) 的系数,最后把两个多项式乘起来,然后只需要看 (2 imes b[j])作为次数在这个多项式中系数的值即可,系数为几,就有几种方案。

    • 对于多项式乘法,用 (NTT) 完成即可,也就是一到快速数论变换的裸题。

    • 需要注意的就是数组中的数的范围是 (-30000sim 30000),我们要的多项式次数需要正数,因此给每个数加上 (30000) 即可。

    代码:

    const int N = 300010;
    const int Mod = 998244353;
    int n,m,L,R[N],g[N],a[N],b[N];
    LL x[N],ci[N];
     
    int gi()
    {
      int x=0,res=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
      while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
      return x*res;
    }
     
    inline int QPow(int d,int z)
    {
      int ans=1;
      for(;z;z>>=1,d=1ll*d*d%Mod)
        if(z&1)ans=1ll*ans*d%Mod;
      return ans;
    }
     
    inline void NTT(int *A,int f)
    {
      for(int i=0;i<n;++i)if(i<R[i])swap(A[i],A[R[i]]);
      for(int i=1;i<n;i<<=1){
        int gn=QPow(3,(Mod-1)/(i<<1)),x,y;
        for(int j=0;j<n;j+=(i<<1)){
          int g=1;
          for(int k=0;k<i;++k,g=1ll*g*gn%Mod){
    	x=A[j+k];y=1ll*g*A[i+j+k]%Mod;
    	A[j+k]=(x+y)%Mod;A[i+j+k]=(x-y+Mod)%Mod;
          }
        }
      }
      if(f==1)return;reverse(A+1,A+n);
      int y=QPow(n,Mod-2);
      for(int i=0;i<n;++i)A[i]=1ll*A[i]*y%Mod;
    }
    int main(){
        int m1,m2,m3,l=0;
        long long c1,c2;
        scanf("%d",&m1);
        for(int i=0;i<m1;++i){
            int num;
            cin>>num;
            a[num+30000]=1;
            c1=max(c1,1ll*num+30000);
        }
        scanf("%d",&m2);
        for(int i=0;i<m2;++i){
            scanf("%lld",&x[i]);
            x[i]+=30000;
        }
        scanf("%d",&m3);
        for(int i=0;i<m3;++i){
            int num;
            cin>>num;
            b[num+30000]=1;
            c2=max(c2,1ll*num+30000);
        }
        c1--;
        c2--;
        for(c2+=c1,n=1;n<=c2;n<<=1,++L);
        for(int i=0;i<n;++i)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        NTT(a,1);NTT(b,1);
        for(int i=0;i<n;++i)a[i]=1ll*a[i]*b[i]%Mod;
        NTT(a,-1);
        //memset(ci,0,sizeof ci);
        long long ans=0;
        for(int i=0;i<m2;i++){
            ans+=1ll*a[x[i]*2];
        }
        cout<<ans;
        return 0;
    }
    
    越自律,越自由
  • 相关阅读:
    mysql 创建++删除 数据表
    mac 配置apache
    mac 安装mysql
    mysql 创建++删除 数据库
    配置默认编码为utf8
    mysql 添加用户
    mysql 查看库结构---查看表结构
    centos7
    centOS 7 安装mysql
    修改字符集
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/14336726.html
Copyright © 2011-2022 走看看