CodeTON Round 4 (Div. 1 + Div. 2, Rated, Prizes!) (ABCD题解)

A: 简单策略

B: 简单数学 

C: 也算数学吧 

D  还是数学吧+简单模拟,感觉难度比C低。

今晚这场个人感觉难度比较低一点(前四题)

A

题意:

问:是否存在a的一个子串p, 使得pi=I;

解:只需存在一个i,满足ai<=i即可

  1. void solve()
  2. {
  3.     int n;
  4.     cin>>n;
  5.     for(int i=1;i<=n;i++)
  6.         cin>>a[i];
  7.     bool prime=false;
  8.     for(int i=1;i<=n;i++)
  9.     if(a[i]<=n&&i>=a[i])
  10.         prime=true;
  11.     if(prime)
  12.         cout<<"YES"<<endl;
  13.     else
  14.         cout<<"NO"<<endl;
  15. }

B:

题意:

对于每个数,可以进行如下操作:

 1:  x=x*2-1

 2:  x=x*2+1

初始手上有一个数为1,问是否可以对其操作不大于40次得到一个给定的数n

若可以,输出给定的操作序列。

解:将数看成二进制的表达,

1操作就是整体左移1,将最低位的1改为0同时将后面的数置为1

2 操作就是整体左移1,最后一位的0 加上1;

手动模拟发现:

1       ->    11     or    1  

11     ->    111    or   101

111   ->    1111  or   1101

101   ->    1011  or   1001

很容易发现规律以及构造方案。

将给定的n分解为2进制表达,若最低位不为1 则无解

否则先将1 进行2操作,然后观察 观察n除了最高位以外的当前位置,为1进行2操作,为0进行1操作

  1. void solve()
  2. {
  3.     int n;
  4.     cin>>n;
  5.     vector<int> v;
  6.     while(n)
  7.     {
  8.         v.push_back(n%2);
  9.         n>>=1;
  10.     }
  11.     int num=v.size();
  12.     if(v[0]!=1)
  13.         cout<<-1<<endl;
  14.     else
  15.     {
  16.         cout<<num-1<<endl;
  17.         cout<<2<<" ";
  18.         for(int i=1;i<=num-2;i++)
  19.             if(v[num-1-i]==1)
  20.                 cout<<2<<" ";
  21.             else
  22.                 cout<<1<<" ";
  23.         cout<<endl;
  24.     }
  25. }

C:

给定数组n

操作1  删除任意位置一个数,代价c

操作2  在任意位置插入任意一个数,代价d

问,将数组n转化成一个长度为p(p>0)的排列,最小代价是多少

解:

先将数组去重,删除重复元素的代价是一定要付出的。

Sort

特判: 将数组转化为1的排列 所需的代价

有点递推的影子,

将数组构造成长度为a[i]所需的代价,为构造成a[i-1]所需的代价+ 补上中间缺少的数的代价 + ( -d ,   (构造成a[i-1]的代价比构造成a[i]的代价多删除了 一个数a[i]  )   )

Res取min  (细节处还需处理)

 

D

题意:

蜗牛爬树,树高h米(未知),白天爬a米,晚上休息掉落b米,(a>b),需要爬行n天

q个操作,

  1操作: 给定,a,b,n,若不与先前条件矛盾,则将其添加到限制条件里面。否则无视

  2操作:   给定a,b;  问要爬几天; 如果不确定输出-1,如果确定则输出对应天数

解:

未知树高,设树高的范围为[hl,hr]

对于a,b,n; 由数学关系分析可知:

If n==1 

       则 hr<=a

Else

       n*a-(n-1)*b>=hr

       hl>(n-1)*a-(n-2)*b

对于1操作,若由当前abn确定的l r范围不涵盖在之前的范围里面,则矛盾

                                                         涵盖在之前的范围里面的话,则缩小范围

  1. if(op==1)
  2.         {
  3.             int a,b,n;
  4.             cin>>a>>b>>n;
  5.             bool prime=true;
  6.             if(n==1)
  7.             {
  8.                 ll h2=a;
  9.                 if(h2<hl)
  10.                     prime=false;
  11.                 else
  12.                     hr=min(hr,h2);
  13.             }
  14.             else
  15.             {
  16.                 ll h1=(ll)(n-1)*a-(ll)(n-2)*b+1;
  17.                 ll h2=(ll)n*a-(ll)(n-1)*b;
  18.                 if(h2<hl||h1>hr)
  19.                     prime=false;
  20.                 else
  21.                 {
  22.                     hr=min(hr,h2);
  23.                     hl=max(hl,h1);
  24.                 }
  25.             }
  26.             if(prime)
  27.                 cout<<1<<" ";
  28.             else
  29.                 cout<<0<<" ";
  30.         }

对于2操作,可定量计算,分析天数是否为1即可

  1. else
  2.         {
  3.             int a,b;
  4.             cin>>a>>b;
  5.             ll res=-1;
  6.             if(hr<=a)   //一天内可以爬完
  7.                 res=1;
  8.             else
  9.             {
  10.                 //分别计算左右边界所需要的天数
  11.                 ll n1=(hr-b+a-b-1)/(a-b);
  12.                 ll n2=(hl-b+a-b-1)/(a-b);
  13.                 if(n1==n2)
  14.                     res=n1;
  15.             }
  16.             cout<<res<<" ";
  17.         }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值