• codeforces #299 div 2


    (总算是5题都做完了- -)

    暂时做了4题,先放一下有时间做最后一题(当然如果我真的能做出的话。。。)(看了大神的代码总算是理解了E题,做完发现也没那么难,果然想出一个思路的过程对于我这种弱渣来说还是太强求了啊。。。)

    A题:

    英文单词别拼错就没什么问题吧

    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    char str[10][10] = {"" , "" , "twenty" , "thirty" , "forty" , "fifty" , "sixty" , "seventy" ,"eighty" , "ninety"};
    char single[10][10] = {"zero" , "one","two","three","four","five","six","seven","eight","nine"};
    char dou[10][10] = {"ten" ,"eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"};
    int main()
    {
        int x;
        while(~scanf("%d" , &x)){
            if(x<10){
                printf("%s
    " , single[x]);
            }
            else if(x<20){
                printf("%s
    " , dou[x%10]);
            }
            else{
                int tmp = x%10;
                printf("%s" , str[x/10]);
                if(tmp){
                    printf("-%s" , single[tmp]);
                }
                printf("
    ");
            }
        }
        return 0;
    }
    View Code

    B题:
    给定一个1~n的范围,问这个范围内只包含4或者7的数字有多少个

    假设n是一个长度为l的整数,那么肯定所有 <l 长度的整数包含4,7的都能取到

    就是(2^1+2^2+...2^(l-1))

    那么就要确定 l 位整数的情况,不断从前往后按照那时的位置上的数字进行判断

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int dig[15];
    
    int qpow(int digit)
    {
        int a=2 , b=digit , ans=1;
        while(b)
        {
            if(b&1) ans*=a;
            a*=a;
            b>>=1;
        }
        return ans;
    }
    
    int getDigit(int x)
    {
        int ans=0;
        while(x){
            x/=10;
            ans++;
        }
        return ans;
    }
    
    void getHead(int x , int len)
    {
        int  index=len;
        while(x){
            dig[index--]=x%10;
            x/=10;
        }
    }
    
    int main()
    {
        int n;
        while(~scanf("%d" , &n))
        {
            int len = getDigit(n);
            int ans=0;
            for(int i=1 ; i<=len-1 ; i++)
                ans+= qpow(i);
            if(ans == 1) ans-=1;
            getHead(n , len);
            for(int i=1 ; i<=len ; i++){
                 //   cout<<dig[i]<<endl;
                if(dig[i]>7){
                    ans += qpow(len-i+1);
                    break;
                }
                else if(dig[i] == 7){
                    ans += qpow(len-i);
                    if(i == len) ans+=1;
                }
                else if(dig[i]>4){
                    ans += qpow(len-i);
                    break;
                }
                else if(dig[i]==4){
                    if(i == len) ans+=1;
                    continue;
                }
                else break;
            }
            printf("%d
    " , ans);
        }
        return 0;
    }
    View Code

    C题:

    一个二分题,当且仅当t在,第一个数时输出-1 , 否则二分判断 t>=最大数,且所有数之和<=t*m即可,这个略微想一下就好了,注意乘法溢出,我在这一直wa

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define N 1000005
    int l,t,m;
    int a , b , n;
    #define ll long long
    
    bool check(int mid)
    {
        ll cnt = mid-l+1;
        ll st = a+(ll)(l-1)*b , la=(ll)(mid-1)*b+a;
        if(t>=la && (st+la)*cnt/2<=(ll)t*m) return true;
        else return false;
    }
    
    int bin_search()
    {
        if(a+(ll)(l-1)*b > (ll)t) return -1;
        int left = l , right = N , ans = l;
        while(left<=right)
        {
            int mid = left+(right-left)/2;
            if(check(mid)){
                left = mid+1;
                ans = mid;
            }else right=mid-1;
        }
        return ans;
    }
    
    int main()
    {
       // freopen("a.in" , "r" , stdin);
    
        while(~scanf("%d%d%d" , &a , &b , &n))
        {
            for(int i=1 ; i<=n ; i++){
                scanf("%d%d%d" , &l , &t , &m);
                printf("%d
    " , bin_search());
            }
        }
        return 0;
    }
    View Code

    D题:

    后缀数组题,这里虽然一看就想到暴力,但是看一下时间复杂度就呵呵了

    利用后缀数组判断当前位置插入一个新的p , 覆盖前一个p的时候是否有冲突即可

    当前位置 cur , 其实就是判断cur的后缀是不是 0 开头的子串

    然后就用vis[]保存插在当前点是否影响即可

    然后i=1~m按顺序查询,单位时间内就解决了

    这里各种特殊情况要考虑,我太欠缺考虑了,完全是依赖cf上可以错了看数据慢慢改对的。。。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define N 1000005
    #define ll long long
    const int MOD = 1e9+7;
    
    char str[N];
    int a[N] , n , m;
    int r[N] , sa[N] , height[N] , rank[N] , wa[N] , wb[N] , wsf[N] , wv[N];
    bool vis[N];
    
    int cmp(int *r , int a , int b , int l)
    {
        return r[a]==r[b] && r[a+l]==r[b+l];
    }
    
    void get_sa(int *r , int *sa , int n , int m)
    {
        int *x=wa , *y=wb , *t;
        int i,j,p;
        for(i=0 ; i<m ; i++) wsf[i]=0;
        for(i=0 ; i<n ; i++) wsf[x[i]=r[i]]++;
        for(i=1 ; i<m ; i++) wsf[i]+=wsf[i-1];
        for(i=n-1 ; i>=0 ; i--) sa[--wsf[x[i]]]=i;
    
        p=1 ;
        for(j=1 ; p<n ; j*=2 , m=p){
            for(p=0 , i=n-j ; i<n ; i++) y[p++] = i;
            for(i=0 ; i<n ; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    
            for(i=0 ; i<n ; i++) wv[i]=x[y[i]];
            for(i=0 ; i<m ; i++) wsf[i]=0;
            for(i=0 ; i<n ; i++) wsf[wv[i]]++;
            for(i=1 ; i<m ; i++) wsf[i]+=wsf[i-1];
            for(i=n-1 ; i>=0 ; i--) sa[--wsf[wv[i]]]=y[i];
    
            t=x , x=y , y=t;
            x[sa[0]]=0;
            for(p=1 , i=1 ; i<n ; i++)
                x[sa[i]] = cmp(y , sa[i-1] , sa[i] , j)?p-1:p++;
        }
    }
    
    void callHeight(int *r , int *sa , int n , int m)
    {
        int i , j , k=0;
        for(i=1 ; i<=n ; i++) rank[sa[i]]=i;
        for(i=0 ; i<n ; height[rank[i++]]=k)
            for(k?k--:0 , j=sa[rank[i]-1] ; r[i+k] == r[j+k] ; k++) ;
        return;
    }
    
    void biaoji(int n)
    {
        memset(vis , 0 , sizeof(vis));
        vis[0]=true;
        int order = 0; //记录以开头为起点的排名
        for(int i=1 ; i<=n ; i++){
            if(sa[i] == 0) order = i;
        }
        int len=N;
        for(int i=order ; i>=1 ; i--){
            int pos = sa[i-1];
            len = min(len , height[i]);
            if(pos+len>=n) vis[pos]=true;
        }
        len=N;
        for(int i=order+1 ; i<=n ; i++){
            int pos = sa[i];
            len = min(len , height[i]);
            if(pos+len>=n) vis[pos]=true;
        }
    }
    
    int qpow(int cnt)
    {
        if(!cnt) return 0;
        ll ans = 1 , a = 26 ;
        while(cnt)
        {
            if(cnt&1) ans = (ans*a)%MOD;
            a = (a*a)%MOD;
            cnt>>=1;
        }
        return (int)ans;
    }
    
    int main()
    {
       // freopen("a.in" , "r" , stdin);
    
        while(~scanf("%d%d" , &n , &m))
        {
            scanf("%s" , str);
            for(int i=0 ; i<m ; i++) scanf("%d" , a+i);
            sort(a , a+m);
    
            int len = strlen(str);
            for(int i=0 ; i<len ; i++){
                r[i] = (int)str[i];
            }
            r[len]=0;
            get_sa(r , sa , len+1 , 128);
            callHeight(r , sa , len , 128);
            biaoji(len);
    
            int cnt = a[0]-1;
            bool flag = true;
            for(int i=1 ; i<m ; i++){
                int dis = a[i]-a[i-1];
                if(dis>=len){
                    cnt+=dis-len;
                }else{
                    if(!vis[dis]) {
                      //  cout<<i<<" "<<dis<<endl;
                        flag = false;
                        break;
                    }
                }
            }
            cnt+=n+1-a[m-1]-len;
            int ans;
            if(!flag){
             //   cout<<"exist "<<endl;
                ans = 0;
    
            }
            else if(m == 0){
                ans = qpow(n);
            }
            else{
                   // cout<<"no "<<endl;
                if(cnt)
                    ans = qpow(cnt);
                else ans=1;
            }
            printf("%d
    " , ans);
        }
        return 0;
    }
    View Code

     E题:

    题目大意就是希望找到一个可能的游泳长度和跑步长度,对应那个队员的两种速度使其有机会夺冠,输出可能夺冠的队员编号

    我们很容易就能想到,如果一个队员其中一项速度是最大的,那么他必然是能夺冠的

    我们从游泳速度从上到下依次将当前跑步所能达到最快速度的人添加进入数组,结构体只保存s(swimming) , r(running)

    当我们每次添加进一个元素时,当前元素是因为跑步最快所以不用删除,那么如果数组中除了游泳最快的那个无需考虑,中间的队员两个速度被夹在中间,此时要考虑能不能存在一个这样的lenS , lenR 使其夺冠

    每次拿三个人的只进行考虑

    比如这里举例 s1:1 , r1:3     s2:2,r2:2     s3:3,r3:1

    那么假设这样的长度存在,设游泳长度为x , 跑步长度为y

    那么

    t1=x/1+y/3

    t2=x/2+y/2

    t3=x/3+y/1

    2号能夺冠,那么t2<=t1 && t2<=t3

    t2<=t1-> x/y>=(1/2-1/3)/(1/1-1/2) = 1/3

    t2<=t3 -> x/y<=(1/1-1/2)/(1/2-1/3) = 3/1

    那么 1/3<=x/y<=3/1 成立,所以2号能夺冠

    根据上述例子就可以自己计算了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <string>
     7 #include <set>
     8 #include <map>
     9 using namespace std;
    10 #define N 10000
    11 #define ll long long
    12 #define eps 1e-9
    13 int run[N*20+10]; //游泳速度为i的人中跑步速度最快达到run[i]
    14 
    15 struct Ath{
    16     int s , r;
    17     Ath(int s=0 , int r=0):s(s),r(r){}
    18 }ath[N*20+10];
    19 int k , s[N*20+10] , r[N*20+10];
    20 
    21 bool can_win(int s1 , int r1 , int s2 , int r2 , int s3 , int r3)
    22 {
    23     //s1<s2<s3 , r1>r2>r3 , 判断s2,r2在包夹下能否有机会夺冠
    24     double t1 = (1.0/r2-1.0/r1) / (1.0/s1-1.0/s2);
    25 
    26     double t2 = (1.0/r3-1.0/r2) / (1.0/s2-1.0/s3);
    27   //  cout<<t1<<" "<<t2<<endl;
    28     if(t2-t1>=-eps) return true;
    29     else return false;
    30 }
    31 
    32 int main()
    33 {
    34   //  freopen("a.in" , "r" , stdin);
    35     int n;
    36     while(~scanf("%d" , &n))
    37     {
    38         memset(run , 0 , sizeof(run));
    39 
    40         for(int i=1 ; i<=n ; i++){
    41             scanf("%d%d" , &s[i] , &r[i]);
    42             run[s[i]] = max(run[s[i]] , r[i]);
    43         }
    44         k=0;
    45         int i;
    46         for(i=N ; i>=0 ; i--){
    47             if(run[i]){
    48                 ath[k++] = Ath(i , run[i]);
    49                 break;
    50             }
    51         }
    52         for(i=i-1 ; i>=0 ; i--){
    53             run[i] = max(run[i] , run[i+1]);
    54             if(run[i] > run[i+1]){
    55                 while(k>1){
    56                     if(!can_win(i , run[i] , ath[k-1].s , ath[k-1].r , ath[k-2].s , ath[k-2].r)){
    57                         k--;
    58                     }else
    59                         break;
    60                 }
    61                 ath[k++] = Ath(i , run[i]);
    62             }
    63         }
    64         map<int , int> m;
    65         for(int i=0 ; i<k ; i++){
    66             m[ath[i].s] = ath[i].r;
    67         }
    68         bool flag=true;
    69         for(int i=1 ; i<=n ; i++){
    70             if(m[s[i]] == r[i]){
    71                 if(flag) printf("%d" , i);
    72                 else printf(" %d" , i);
    73                 flag = false;
    74             }
    75         }
    76         puts("");
    77     }
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    11 Apr 18 类与对象 对象的使用 一切皆对象
    10 Apr 18 项目构架 hashlib模块 subprocess模块 configparser模块 面向对象的编程 类与对象
    9 Apr 18 shelve模块 xml模块 re模块
    8 Apr 18 包的使用 常用模块
    定义一个Student类,包含名字一个数据成员,定义无参构造函数、有参构造函数、拷贝构造函数、析构函数及对于名字的封装函数,在main函数中实例化Student对象,并访问相关函数,观察运行结果。
    皮马印第安人糖尿病数据集免费下载分享
    机器学习之模型训练(二)皮马印第安人糖尿病数据集
    anaconda的虚拟环境sklearn中如何安装pandas
    人工智能之模型评估之参数选择
    人工智能之模型评估之数据分离
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4430820.html
Copyright © 2020-2023  润新知