zoukankan      html  css  js  c++  java
  • UPC2018组队训练赛第七场

    题目来自ICPC 2017 Japan Tsukuba

     


     

    A题:Secret of Chocolate Poles

    有三种巧克力,分别是厚度为1的白色巧克力,厚度为1或者k的黑色巧克力。要求把巧克力放到高度为 l 的盒子里,并且要黑白相间,底部和顶部必须都是黑色的

    当l=1,ans=1;当l<k,ans=(l-1)/2+1;当l=k,ans=(l-1)/2+2;当l>k时,就可以转化成排列组合问题了,枚举厚度为k的黑色巧克力数目i,然后对于每一种情况,再枚举厚度为1的黑色巧克力的数目j,那么此时排列的情况就是(i+j)! / ( i! * j! )。最后取和就行了。

    因为阶乘会爆longlong,所以就用java写的

     1 import java.util.*;
     2 import java.math.BigInteger;
     3 public class Main {
     4  
     5     public static void main(String[] args) {
     6         // TODO Auto-generated method stub
     7         Scanner cin = new Scanner(System.in);
     8         BigInteger[]fac=new BigInteger[60];
     9         fac[0]=BigInteger.valueOf(1);
    10         BigInteger tmp;
    11         for(int i=1;i<60;i++) {
    12             tmp=BigInteger.valueOf(i);
    13             fac[i]=fac[i-1].multiply(tmp);
    14         }
    15         int l,k;
    16         l= cin.nextInt();
    17         k=cin.nextInt();
    18         int flag=0;
    19         long aa=0;
    20         BigInteger ans=BigInteger.valueOf(0);
    21         if(l==1)    aa=1;
    22         else if(l<k) aa=(l-1)/2+1;
    23         else if(l==k)   aa=(l-1)/2+2;
    24         else
    25         {
    26             flag=1;
    27             BigInteger tt,pp;
    28             for(int i=0;i*(k+1)<=(l-1);i++)
    29             {
    30                 for(int j=0;j*2<=(l-1-i*(k+1));j++)
    31                 {
    32                     tt=fac[i].multiply(fac[j]);
    33                     pp=fac[i+j].divide(tt);
    34                     ans=ans.add(pp);
    35                 }
    36             }
    37             for(int i=0;i*2<=(l-k);i++)
    38             {
    39                 for(int j=0;j*(k+1)<=(l-k-i*2);j++){
    40                     tt=fac[i].multiply(fac[j]);
    41                     pp=fac[i+j].divide(tt);
    42                     ans=ans.add(pp);
    43                 }
    44             }
    45         }
    46         if(flag==1)
    47             System.out.println(ans);
    48         else
    49         {
    50             ans=BigInteger.valueOf(aa);
    51             System.out.println(ans);
    52         }
    53              
    54     }
    55  
    56 }
    View Code

    之后看了大佬的代码https://www.cnblogs.com/clrs97/p/8537178.html  发现可以用dp

    f[i][j]代表高度为i,顶层颜色为j的方案数。(j=0,表示黑色,j=1表示白色)

     1 #include<cstdio>
     2 typedef __int128 lll;
     3 const int N=200;
     4 lll f[N][2],ans;//dark white
     5 int l,k,i;
     6 void write(lll x){
     7     if(x>=10)write(x/10);
     8     x%=10;
     9     printf("%d",(int)(x));
    10 }
    11 int main(){
    12     scanf("%d%d",&l,&k);
    13     f[1][0]++;
    14     f[k][0]++;
    15     for(i=1;i<=l;i++){
    16         f[i+1][1]+=f[i][0];
    17         f[i+1][0]+=f[i][1];
    18         f[i+k][0]+=f[i][1];
    19     }
    20     for(i=1;i<=l;i++)ans+=f[i][0];
    21     write(ans);
    22 }
    View Code

    B题:Parallel lines

    给偶数个点,两点形成直线,保证任意三点不在同一条直线,问最多能找到多少对平行线

    写个搜索,找到所有的直线的可能情况,然后用vector存直线的两点,之后遍历找平行线。找平行线的话,可以用向量

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 struct node
     5 {
     6     int x,y;
     7 } Point[20];
     8 int n,ans=-1;
     9 bool vis[20];
    10 vector<pair<int,int> >line;
    11 void countt()
    12 {
    13     int tmp=0;
    14     for(int i=0; i<line.size(); i++)
    15     {
    16         int x1=Point[line[i].first].x-Point[line[i].second].x;
    17         int y1=Point[line[i].first].y-Point[line[i].second].y;
    18         for(int j=i+1; j<line.size(); j++)
    19         {
    20             int x2=Point[line[j].first].x-Point[line[j].second].x;
    21             int y2=Point[line[j].first].y-Point[line[j].second].y;
    22             if(x1*y2==x2*y1)
    23             {
    24                 tmp++;
    25             }
    26         }
    27     }
    28     ans=max(ans,tmp);
    29 }
    30 void dfs(int now)
    31 {
    32     if(now==n+1)
    33     {
    34         countt();
    35         return;
    36     }
    37     if(vis[now])
    38     {
    39         dfs(now+1);
    40     }
    41     else
    42     {
    43         for(int i=1; i<=n; i++)
    44         {
    45             if(vis[i]||i==now)
    46             {
    47                 continue;
    48             }
    49             line.push_back(make_pair(now,i));
    50             vis[now]=vis[i]=1;
    51             dfs(now+1);
    52             line.pop_back();
    53             vis[now]=vis[i]=0;
    54         }
    55     }
    56 }
    57 int main()
    58 {
    59     scanf("%d",&n);
    60     for(int i=1; i<=n; i++)
    61     {
    62         scanf("%d %d",&Point[i].x,&Point[i].y);
    63     }
    64     dfs(1);
    65     printf("%d
    ",ans);
    66     return 0;
    67 }
    68  
    View Code

    C题:Medical Checkup

    有很多个窗口,有n个人,每个人去窗口办理业务的时间不同,问在t分钟时,每个人分别在哪个窗口

    首先求一下每个人在第一个窗口待的时间,然后遍历每个人,如果t小于当前这个人在第一个窗口待的时间,直接输出1;否则,我们可以发现每个人在其他的窗口待的时间是相同的,如果当前这个人办理业务需要的时间小于他前一个人的,那么他在以后的每一个窗口所带的时间就是h[i]=h[i]+h[i-1]-h[i]=h[i-1],不小于的话就直接是他自己办理业务的时间h[i],对于每一个人,用 tt=t-sum[i] 表示这个人离开第一个窗口后还剩的时间,用 tt/h[i]+1,代表在tt这段时间里他能往后走多少个窗口,最后再加上第一个窗口(tt/h[i]+2)就是最终所在的窗口编号了。

     1  
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=100050;
     5 int n;
     6 ll h[N],sum[N],t;
     7 int main()
     8 {
     9     scanf("%d %lld",&n,&t);
    10     for(int i=1;i<=n;i++)
    11     {
    12         scanf("%lld",&h[i]);
    13         sum[i]=sum[i-1]+h[i];
    14     }
    15     for(int i=1;i<=n;i++)
    16     {
    17         ll tt=t-sum[i];
    18         if(tt<0)
    19         {
    20             printf("1
    ");
    21             continue;
    22         }
    23         else
    24         {
    25             if(h[i]<h[i-1])
    26             {
    27                 h[i]+=(h[i-1]-h[i]);
    28             }
    29             ll ans=tt/h[i];
    30             ans+=2;
    31             printf("%lld
    ",ans);
    32         }
    33     }
    34     return 0;
    35 }
    View Code

    G题:Rendezvous on a Tetrahedron

    把三维展成二维,可以发现有循环节

    把最终点的坐标转化到第一个循环节里,再讨论在哪个区域,然后再与输入的边匹配,得到最终的面的编号

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define PI acos(-1.0)
     4 struct node
     5 {
     6     double x,y;
     7 }p1,p2;
     8 double getpi(double x)
     9 {
    10     return x*PI/180.0;
    11 }
    12 double fun(double x)
    13 {
    14     while(x>2)
    15     {
    16         x-=2;
    17     }
    18     return x;
    19 }
    20 int findArea(node p)
    21 {
    22     if(p.x+p.y-1<0||(p.x+p.y-3>0&&p.x<2&&p.y<2))
    23         return 1;
    24     else if((p.x+p.y-1>0&&p.x<1&&p.y<1)||(p.x+p.y-3<0&&p.x<2&&p.x>1&&p.y<2&&p.y>1))
    25         return 2;
    26     else if((p.x+p.y-2<0&&p.x>1&&p.x<2&&p.y<1)||(p.x+p.y-2>0&&p.x<1&&p.y>1&&p.y<2))
    27         return 3;
    28     else if((p.x+p.y-2<0&&p.x<1&&p.y>1&&p.y<2)||(p.x+p.y-2>0&&p.x>1&&p.x<2&&p.y<1))
    29         return 4;
    30 }
    31 int findAns(char ch,int a)
    32 {
    33     if(ch=='B')
    34     {
    35         if(a==1)    return 1;
    36         else if(a==2)   return 4;
    37         else if(a==3)   return 3;
    38         else if(a==4)   return 2;
    39     }
    40     else if(ch=='C')
    41     {
    42         if(a==1)    return 2;
    43         else if(a==2)   return 4;
    44         else if(a==3)   return 1;
    45         else if(a==4)   return 3;
    46     }
    47     else if(ch=='D')
    48     {
    49         if(a==1)    return 3;
    50         else if(a==2)   return 4;
    51         else if(a==3)   return 2;
    52         else if(a==4)   return 1;
    53     }
    54 }
    55 int main()
    56 {
    57     char op1[3],op2[3];
    58     int d1,l1,d2,l2;
    59     scanf("%s%d%d",op1,&d1,&l1);
    60     scanf("%s%d%d",op2,&d2,&l2);
    61  
    62     p1.x=l1*sin(getpi(60.0-d1*1.0))/sin(getpi(120.0));
    63     p1.y=l1*sin(getpi(d1*1.0))/sin(getpi(120.0));
    64  
    65     p2.x=l2*sin(getpi(60.0-d2*1.0))/sin(getpi(120.0));
    66     p2.y=l2*sin(getpi(d2*1.0))/sin(getpi(120.0));
    67  
    68     p1.x=fun(p1.x);
    69     p1.y=fun(p1.y);
    70  
    71     p2.x=fun(p2.x);
    72     p2.y=fun(p2.y);
    73  
    74     int a1=findArea(p1);
    75     int a2=findArea(p2);
    76  
    77     int ans1=findAns(op1[0],a1);
    78     int ans2=findAns(op2[0],a2);
    79  
    80     if(ans1==ans2)  printf("YES
    ");
    81     else            printf("NO
    ");
    82  
    83     return 0;
    84  
    85 }
    View Code

    I题:Starting a Scenic Railroad Service

    参考https://blog.csdn.net/xnmzdxws/article/details/80070867

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=2e5;
     4 int n,a[N+5],b[N+5],ans1,ans2,r[N+5],sn,sa[N+5],sb[N+5],sc[N+5];
     5 int main()
     6 {
     7     scanf("%d",&n);
     8     for(int i=1;i<=n;i++)
     9     {
    10         scanf("%d%d",&a[i],&b[i]);
    11         sa[a[i]]++;
    12         sb[b[i]]++;
    13         sc[a[i]]++;
    14         sc[b[i]]--;
    15         sn=max(sn,b[i]);
    16     }
    17     for(int i=1;i<=sn;i++)
    18     {
    19         sa[i]+=sa[i-1];
    20         sb[i]+=sb[i-1];
    21     }
    22     for(int i=1;i<=n;i++)
    23         ans1=max(ans1,sa[b[i]-1]-sb[a[i]]);
    24     for(int i=1;i<=sn;i++)
    25     {
    26         sc[i]+=sc[i-1];
    27         ans2=max(ans2,sc[i]);
    28     }
    29     printf("%d %d
    ",ans1,ans2);
    30     return 0;
    31 }
    View Code

    如有错误,请指正,感谢!
  • 相关阅读:
    Python动态展示遗传算法求解TSP旅行商问题
    MOEAD算法中均匀权向量的实现---Python
    HDU 5294 多校第一场1007题 最短路+最小割
    POJ 3261 Milk Patterns sa+二分
    HDU 4292 FOOD 2012 ACM/ICPC Asia Regional Chengdu Online
    CodeForces 201A Clear Symmetry
    POJ 1679 The Unique MST 确定MST是否唯一
    POJ 3268 Silver Cow Party 最短路 基础题
    POJ 2139 SIx Degrees of Cowvin Bacon 最短路 水題
    POJ2229 Sumsets 基礎DP
  • 原文地址:https://www.cnblogs.com/scott527407973/p/9556301.html
Copyright © 2011-2022 走看看