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 }
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 }
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 }