BestCoder 2nd Anniversary

  1001:只要将一个非零数字拆出来,作为小的那个数,另外的数字从大到小排列组成另外一个数字相加即可。代码如下(细节有点多):

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N = (int)1e7 + 5;
 4 
 5 char s[N];
 6 int cnt[10];
 7 
 8 bool isok()
 9 {
10     // 至少要有一个不是0的数字当做第一个数字的开头
11     for(int i=1;i<=9;i++) if(cnt[i]) return true;
12     return false;
13 }
14 
15 int main()
16 {
17     int T;
18     scanf("%d",&T);
19     getchar();
20     while(T--)
21     {
22         memset(cnt,0,sizeof(cnt));
23         for(;;)
24         {
25             char c = getchar();
26             if(c == '
') break;
27             cnt[c-'0']++;
28         }
29         int first=-1;
30         for(int i=1;i<=9;i++) //找第一个不是0的数字,当做第二个数
31         {
32             if(cnt[i])
33             {
34                 cnt[i]--;
35                 first = i;
36                 break;
37             }
38         }
39         if(!isok())
40         {
41             puts("Uncertain");
42             continue;
43         }
44 
45         int up = first,tot=0;
46         for(int i=0;i<=9;i++)
47         {
48             for(int j=1;j<=cnt[i];j++)
49             {
50                 s[tot++] = i + '0';
51             }
52         }
53 
54         // 模拟加法进位
55         for(int i=0;i<tot;i++)
56         {
57             if(up + s[i]-'0' > 9)
58             {
59                 s[i] = s[i] + up - 10;
60                 up = 1;
61             }
62             else
63             {
64                 s[i] = s[i] + up;
65                 up = 0;
66                 break;
67             }
68         }
69 
70         if(up == 1) printf("1");
71         for(int i=tot-1;i>=0;i--)
72         {
73             printf("%c",s[i]);
74         }
75         puts("");
76     }
77 }
View Code

  1002:见代码(注释很详细了):

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N = 100000 + 5;
 7 const int mod = 998244353;
 8 
 9 int a[N],b[N],n;
10 
11 ll solve()
12 {
13     // 第一个数字的a和b值肯定相等
14     if(a[1] != b[1]) return 0;
15     ll ret = 1;
16     for(int i=2;i<=n;i++)
17     {
18         // a值是单调不上升,b值是单调不下降。
19         // 如果不满足这两条则没有答案
20         if(a[i]>a[i-1] || b[i]<b[i-1]) return 0;
21         
22         int op = (a[i]!=a[i-1]) + (b[i]!=b[i-1]);
23         // 如果op是2,表示最大值和最小值都发生了改变,
24         // 也就是说第i个数既是最大值也是最小值,显然不可能
25         if(op == 2) return 0;
26         // 如果op是1,这个位置只能放最大值或者最小值改变了的那个值
27         
28         // 如果op是0,表示第i个数可以使夹在最大值和最小值内任意一个没被使用过的数
29         // b[i]-a[i]+1 表示最大值和最小值的这个区间内的数字个数
30         // i-1 表示在这个区间内已经使用了这么多个数字,它们无法在这个位置出现,应排除
31         if(op == 0)
32         {
33             // 用乘法原理叠加
34             ret = ret * (b[i]-a[i]+1 - (i-1)) % mod;
35         }
36     }
37     return ret;
38 }
39 
40 int main()
41 {
42     int T;
43     scanf("%d",&T);
44     while(T--)
45     {
46         scanf("%d",&n);
47         for(int i=1;i<=n;i++) scanf("%d",a+i);
48         for(int i=1;i<=n;i++) scanf("%d",b+i);
49         ll ans = solve();
50         printf("%I64d
",ans);
51     }
52 }
View Code

  1003:利用扫描求出答案。具体见代码(有注释):

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N = 100000 + 5;
 7 
 8 /*
 9     考虑三角形三条边 a,b,c (a >= b) 的关系 a - b < c, a + b > c ,即 c∈(a-b,a+b)
10     这是非法区域,只要在L到R上的区间扫描减去非法区域即可
11 */
12 
13 int n,tot;
14 ll L,R,a[N];
15 struct node
16 {
17     ll l,r;
18     bool operator < (const node& A) const
19     {
20         return l==A.l ? r<A.r : l<A.l;
21     }
22 }P[N];
23 
24 void solve()
25 {
26     // 全集减去非法区域就是答案
27     ll ans = R - L + 1;
28     ll left = L;
29     for(int i=1;i<=tot;i++)
30     {
31         if(P[i].r>=left)
32         {
33             if(P[i].l>=left)
34             {
35                 ans -= P[i].r-P[i].l+1;
36             }
37             else ans -= P[i].r-left+1;
38             left = P[i].r + 1;
39         }
40     }
41     printf("%I64d
",ans);
42 }
43 
44 void init()
45 {
46     tot = 0;
47     scanf("%d%I64d%I64d",&n,&L,&R);
48     for(int i=1;i<=n;i++) scanf("%I64d",a+i);
49     sort(a+1,a+1+n);
50     for(int i=2;i<=n;i++)
51     {
52         // P区域是非法区域
53         P[++tot].l = max(L,a[i]-a[i-1]+1); //左右区间都是开区间
54         P[tot].r = min(R,a[i]+a[i-1]-1);
55         
56         // 下面这句一定要有
57         if(P[tot].l > P[tot].r) tot--;
58     }
59     sort(P+1,P+1+tot);
60 }
61 
62 int main()
63 {
64     int T;
65     scanf("%d",&T);
66     while(T--)
67     {
68         init();
69         solve();
70     }
71 }
View Code
原文地址:https://www.cnblogs.com/zzyDS/p/5680541.html