zoukankan      html  css  js  c++  java
  • cf round #421 div2 C. Mister B and Boring Game(trick)

    链接:http://codeforces.com/contest/820/problem/C

    分析:A完一觉起来发现数据改了,WA掉了。。出题人觉得自己做法错了。。

    首先把字符串记为A1 B1 A2 B2 A3 B3……,事实上,A3与A1完全一样,因此是个周期数列。为了方便,把a记做1,b记做2,以此类推。对于B来说,最优策略是选择与最后a-b个字母其中一个一样的,然后a>=b时,A2就会变成1,2,...,b,1+a,...,2a-b,

    a<b时,就是1到a+1,跳过选择的那个字母。

    周期性证明:按前面的取法,a>b时,A2中[b+1,a]这一段不能取,a<=b时,a不能取,因此A2为从a开始跳过不能取的一段,记A2=A21+A22,A3恰好只需和A22互异,所以可以从1取到a,形成周期,T=2(a+b)。

    由周期性证明易得,在一个周期内,记互异元素个数为t,若a>=b,t=2a-b,否则t=a+1。

    当r-l>=T时,由周期性知,答案为t,否则,对T取余,转化为一个周期内的问题,枚举选择的字母,求一下区间内的最小值即可。

    B1、B2必然选择同一个字母。首先,只要满足贪心,是否选同一字母不影响周期性。考虑mod完的r和l,假设选择不同字母,先考虑l<=r,若r在B2,显然选择不同字母不会更优;若r在B2之前,B2取什么并不影响。如果l>r,即答案为[1,r]加上[l,a+b]的互异元素个数,

    同样,选择不同字母并不会更优,因此枚举时只需要枚举同一个即可。

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 typedef long long ll;
     5 ll a,b,l,r,ans=100,T;
     6 ll Cal(char c){
     7     ll count=0;
     8     char s[100];
     9     for(int i=0;i<a;i++)
    10         s[i]='a'+i;
    11     for(int i=a;i<a+b;i++)
    12         s[i]=c;
    13     int have[26];
    14     memset(have,0,26*sizeof(int));
    15     for(ll i=a+b-1;i>=b;i--){
    16         have[s[i]-'a']=1;
    17     }
    18     ll i=a+b,j=0;
    19     while(i<2*a+b){
    20         while(have[j]){
    21             j++;
    22         }
    23         s[i]=j+'a';
    24         i++;j++;
    25     }
    26     for(int i=2*a+b;i<T;i++)
    27         s[i]=s[i-1];
    28     memset(have,0,26*sizeof(int));
    29     if(l<=r){
    30         for(ll i=l;i<=r;i++){
    31             if(!have[s[i]-'a']){
    32                 count++;have[s[i]-'a']=1;
    33             }
    34         }
    35     }else{
    36         for(ll i=0;i<=r;i++){
    37             if(!have[s[i]-'a']){
    38                 count++;have[s[i]-'a']=1;
    39             }
    40         }
    41         for(ll i=l;i<T;i++){
    42             if(!have[s[i]-'a']){
    43                 count++;have[s[i]-'a']=1;
    44             }
    45         }
    46     }
    47     return count;
    48 }
    49 int main(){
    50     ll t;
    51     cin>>a>>b>>l>>r;
    52     l--;r--;
    53     T=2*(a+b);
    54     if(a>b+1)t=2*a-b;
    55     else t=a+1;
    56     if(r-l>=T)ans=t;
    57     else{
    58         r%=T;l%=T;
    59         for(int i=0;i<a;i++){
    60             ans=min(Cal('a'+i),ans);
    61         }
    62     }
    63     cout<<ans<<endl;
    64     return 0;
    65 }
  • 相关阅读:
    TCP流量控制,拥塞控制原理
    Java数组--求一个数组中连续m个数的和最大的数组组合
    一次使用IDEA编写JDK动态代理Class数组中有关泛型的问题
    Java数组--一个整型数组,给定一个定数,求数组中两个数的和与定数相等
    Java基础知识--Stream接口的理解与应用
    JSAP107
    JSAP106
    JSAP105
    JSAP104
    JSAP103
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7088904.html
Copyright © 2011-2022 走看看