• BestCoder 2nd Anniversary


    Oracle

    Accepts: 599
    Submissions: 2576
    Time Limit: 8000/4000 MS (Java/Others)
    Memory Limit: 262144/262144 K (Java/Others)
    问题描述
    曾经有一位国王,统治着一片未名之地。他膝下有三个女儿。
    
    三个女儿中最年轻漂亮的当属Psyche。她的父亲不确定她未来的命运,于是他来到Delphi神庙求神谕。
    
    神谕可以看作一个不含前导零的正整数 n n。
    
    为了得到真正的预言,他可以将 n n的各个数位重新排列,并将其分成两个不含前导零的正整数。
    
    请你帮助他求出这两个正整数最大的和。如果不存在这样的两个正整数,输出"Uncertain".
    输入描述
    第一行一个整数T T  (1≤T≤10) (1 le T le 10) ,代表数据组数。
    
    接下来T T T行,每行一个正整数n n  (1≤n<1010000000) (1 le n < 10 ^ {10000000}) 
    输出描述
    对于每组数据,输出一个整数表示最大的和。若不存在一种方案,输出"Uncertain".
    输入样例
    3
    112
    233
    1
    输出样例
    22
    35
    Uncertain
    Hint
    对于第一组数据,最优方案是将112 112 分成21 21 1 1 ,最大的和为21+1=22 21 + 1 = 22 。
    
    对于第二组数据,最优方案是将233 233 分成2 2 33 33 ,最大的和为2+33=35 2 + 33 = 35 。
    
    对于第三组数据,显然无法将一个数位分成两部分。
    
    建议使用效率较高的读入方式。
    分析:

    Provider : cxzxxjd

    先记录 0−90-91010个数字分别有多少个。不难看出,最小的一个存在的数字和其余的数字降序排列的相加就是答案,但是最小的那个数字不能是00,因为题面上说明是正整数。将这两个数加起来时,注意处理进位问题。考虑无解的情况,即一串数字中仅存在11个非00数字或不存在。(PS.这道题目原本的时限是1s,考虑到题目的难度和评测机的问题,开了4s4s,大家可以自己在FST以后看一下时间。如果是时限是1s1s的话,sortsort是过不了的,输出也需要优化一下)

    时间复杂度 O(Tn)O(Tn)


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=100000000+9;
    int a[N],b[N];
    char s[N];
    int main()
    {
        //freopen("f.txt","r",stdin);
        int T;scanf("%d",&T);
        while(T--){
            scanf("%s",s);
            int n=strlen(s);
            for(int i=0;i<n;i++){
                a[i]=s[i]-'0';
            }
            sort(a,a+n);
            int i;
            for(i=0;i<n;i++){
                if(a[i]!=0)break;
            }
            if(n-i<=1){
                printf("Uncertain
    ");continue;
            }
            int t=0;
            for(int j=0;j<n;j++){
                if(j!=i)b[t++]=a[j];
            }
            int j;b[n-1]=0;
            t=a[i];
            for(j=0;j<n;j++){
                if(b[j]+t>9)b[j]=b[j]+t-10,t=1;
                else{b[j]=b[j]+t;break;}
            }
            if(b[n-1]==0)n--;
            for(i=n-1;i>=0;i--)printf("%d",b[i]);
            printf("
    ");
            continue;
        }
        return 0;
    }


    Arrange

    Accepts: 221
    Submissions: 1401
    Time Limit: 8000/4000 MS (Java/Others)
    Memory Limit: 262144/262144 K (Java/Others)
    问题描述
    Cupid一不小心将爱情之箭射到了自己,他爱上了Psyche。
    
    这引起了他的母亲Venus的注意。Venus将Psyche带到了一堆打乱的谷堆旁。
    
    这儿共有n n 堆稻谷,编号为1 1 n n 。Psyche需要将这些谷堆以某种顺序排列,设最终排在第i i i位的谷堆是Ai A_i 
    
    她得知了一些该排列的要求:
    
      1. 对于任意整数i∈[1,n] i in [1,n] A1,A2,...,Ai的最小值为Bi B_i 。
    
      2. 对于任意整数i∈[1,n] i in [1,n] A1,A2,...,Ai的最大值为Ci C_i 。
    
    现在Psyche想知道,共有多少种合法的排列。由于答案可能很大,输出时对998244353 998244353 取模。
    输入描述
    第一行,一个整数T T  (1≤T≤15) (1 le T le 15) ,代表数据组数。
    
    对于每组数据,第一行有一个整数n n  (1≤n≤105) (1 le n le 10 ^ 5) ,代表排列大小。
    
    第二行,n n 个整数,第i i 个整数为Bi B_i  (1≤Bi≤n) (1 le B_i le n) 。
    
    第三行,n n 个整数,第i i 个整数为Ci C_i (1≤Ci≤n) (1 le C_i le n) 
    输出描述
    输出T T 行,对于每组数据输出答案对998244353 998244353 取模的结果。
    输入样例
    2
    3
    2 1 1
    2 2 3
    5
    5 4 3 2 1
    1 2 3 4 5
    输出样例
    1
    0
    Hint
    对于第一组数据,只有一种合法的排列(2,1,3) (2,1,3) 。
    
    对于第二组数据,没有合法的排列。
    分析:

    Provider : frank_c1

    首先,根据题意可得B数组应是单调不升的,C数组是单调不降的。

    可以发现A1=B1=C1,所以如果B1≠C1 B_1 eq C_1 无解。

    进一步,我们发现如果Bi<Bi−1 B_i < B_{i-1} Ai=Bi;如果Ci>Ci−1 C_i > C_{i-1} Ai=Ci A_i = C_i 。但是如果Bi<Bi−1Ci>Ci−1 C_i > C_{i-1} 同时满足,就会产生冲突导致无解。

    考虑Bi=Bi−1 B_i = B_{i-1} Ci=Ci−1 C_i = C_{i-1} 同时满足的情况,此时应有Ai∈(Bi,Ci) A_i in (B_i,C_i) Ai A_i 没有在之前使用过。因为(Bi,Ci) (B_i,C_i) 是不断变大的,我们只需维护一下这个区间内有多少值已经被使用过了,用乘法原理统计答案即可。注意到如果某时刻Ai A_i 没有值可以使用,也会导致无解。

    时间复杂度O(Tn) O(Tn)

    #include<cstdio>
    using namespace std;
    const int mod=998244353;
    const int N=1e5+9;
    int a[N],b[N],c[N];
    int main()
    {
        //freopen("f.txt","r",stdin);
        int T;scanf("%d",&T);
        while(T--){
            int n;scanf("%d",&n);
            for(int i=0;i<n;i++)scanf("%d",&b[i]);
            for(int i=0;i<n;i++)scanf("%d",&c[i]);
            int minn=b[0],maxn=c[0];
            if(b[0]!=c[0]){printf("0
    ");continue;}
            int ans=1;
            int i,num=0; 
            for(i=1;i<n;i++){
                if(b[i]==minn&&c[i]==maxn&&num>=0)ans=1LL*ans*num%mod,num--;
                else if(minn>b[i]&&c[i]==maxn)num+=minn-b[i]-1,minn=b[i];
                else if(maxn<c[i]&&b[i]==minn)num+=c[i]-maxn-1,maxn=c[i];
                else break;
            }
            if(i<n)printf("0
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }


    Wool

    Accepts: 109
    Submissions: 770
    Time Limit: 8000/4000 MS (Java/Others)
    Memory Limit: 262144/262144 K (Java/Others)
    问题描述
    黎明时,Venus为Psyche定下了第二个任务。她要渡过河,收集对岸绵羊身上的金羊毛。
    
    那些绵羊狂野不驯,所以Psyche一直往地上丢树枝来把它们吓走。地上现在有n n 根树枝,第i i i根树枝的长度是ai a_i .
    
    如果她丢的下一根树枝可以和某两根树枝形成三角形,绵羊就会被激怒而袭击她。
    
    现在Psyche手中只有长度不小于L L L且不大于R R 的树枝。请你帮忙计算,她下一根可以丢多少种不同长度的树枝而不会把绵羊激怒呢?
    输入描述
    第一行,一个整数T(1≤T≤10) T  (1 le T le 10) ,代表数据组数。
    
    对于每组数据,第一行有三个整数n,L,R n,L,R  (2≤n≤105,1≤L≤R≤1018) (2 le n le 10 ^ 5, 1 le L le R le 10 ^ {18}) 。
    
    第二行,n n 个整数,第i i 个整数为ai a_i  (1≤ai≤1018) (1 le a_i le 10 ^ {18}) ,代表第i i i根树枝的长度。
    输出描述
    输出T T T行,对于每组数据,输出选取方式总数。
    输入样例
    2
    2 1 3
    1 1
    4 3 10
    1 1 2 4
    输出样例
    2
    5
    Hint
    对于第一组数据,可以选用长度为2,2, 3 33333的树枝。
    
    对于第二组数据,可以选用长度为6,7,8,9,10的树枝。
    分析:

    Provider : frank_c1

    考虑三角形三条边a,b,c (a≥b) (a ge b) 的关系a−b<c,a+b>c a - b < c, a + b > c ,即c∈(a−b,a+b) c in (a-b,a+b)

    令加入的边为c c ,枚举所有边作为a a 的情况。对于所有可行的b b ,显然与a a 相差最小的可以让(a−b,a+b) (a-b,a+b) 覆盖范围最大,所以可以贪心地选择不大于a a 的最大的b b

    于是我们可以先将边按长度排序,然后aiai+1建一条线段。线段并是不合法的部分。

    将所有线段按左端点排序,按序扫描一遍,过程中统计答案即可。

    时间复杂度O(Tn logn) O(Tn log n)


    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int mod=998244353;
    const int N=1e5+9;
    typedef long long ll;
    typedef pair<ll,ll>pll;
    pll p[N];
    ll a[N],L,R;
    int n;
    int main()
    {
        int T;scanf("%d",&T);
        while(T--){
            scanf("%d%I64d%I64d",&n,&L,&R);
            for(int i=0;i<n;i++)scanf("%I64d",&a[i]);
            sort(a,a+n);
            for(int i=0;i<n-1;i++){
                p[i].first=a[i+1]-a[i];
                p[i].second=a[i+1]+a[i];
            }
            sort(p,p+n-1);
            ll x=L,ans=0;
            for(int i=0;i<n-1;i++){
                if(p[i].first>=x)ans+=p[i].first-x+1;
                x=max(x,p[i].second);
            }
            if(R-x+1>0)ans+=R-x+1;
            printf("%I64d
    ",ans);
        }
        return 0;
    }





  • 相关阅读:
    【多线程】工具类汇总
    【JVM】GC日志样例解读
    【Docker】
    XXS level5
    XXS level4
    XXS level3
    XXS level2
    SQLI DUMB SERIES-6
    SQLI DUMB SERIES-5
    XXS level1
  • 原文地址:https://www.cnblogs.com/01world/p/5762837.html
Copyright © 2020-2023  润新知