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\n");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("\n");
        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 \neq 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\n");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\n");
        else printf("%d\n",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\n",ans);
    }
    return 0;
}





转载于:https://www.cnblogs.com/01world/p/5762837.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值