SCU-4437 Carries

https://blog.csdn.net/catglory/article/details/46539283

https://blog.csdn.net/u012127882/article/details/46517099

 

学到了很开心

当我们求,有多少个数相加起来会大于某一个常数的时候,只需将原数组排序,然后枚举每一个数就行了,枚举的时候,一个左指针向右移,就是我们正在枚举的数字,而另外一个右指针向左移,而不需要回溯,因为左指针指向的数字变大了,所以右指针右边的不用判断就知道一定会大于这个常数了。这样的话就可以将n方的复杂度变成2*n,所谓的二分解法,与这个也是类似的。二分求解的是,每一个左指针指向的值,与之相加不能超过这个常数的值的位置,实际上就是每次左指针右移时,右指针停住的位置。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 
25 int num[maxn];
26 int a[maxn];
27 int main()
28 {
29 //    ios::sync_with_stdio(false);
30 //    freopen("in.txt","r",stdin);
31 
32     int n;
33     while(scanf("%d",&n)!=EOF){
34         for(int i=1;i<=n;i++){
35             scanf("%d",&num[i]);
36         }
37         int t= 1;
38         ll ans = 0;
39         for(int k=1;k<=9;k++){
40             t*=10;
41             for(int i=1;i<=n;i++){
42                 a[i]=num[i]%t;
43             }
44             sort(a+1,a+1+n);
45 
46             int r = n;
47             for(int i=1;i<=n;i++){
48                 while(r&&a[i]+a[r]>=t){
49                     r--;
50                 }
51 //                fuck(r)
52                 if(i>r){ans+=(n-r-1);}
53                 else{ans+=n-r;}
54 //                fuck(ans)
55             }
56 
57 
58         }printf("%lld\n",ans/2);
59 
60 
61     }
62 
63     return 0;
64 }
View Code

代码几乎是抄的上面两位博主的,毕竟看了别人的代码,思路就固化了。开始不知道输出是答案的两倍,除了一个2就过了。

后来想了一下,应该是重复枚举了,毕竟l最后会超过r,所以要除以2

posted @ 2018-12-03 23:40  断腿三郎  阅读(279)  评论(0编辑  收藏  举报