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 ",ans/2); 59 60 61 } 62 63 return 0; 64 }
代码几乎是抄的上面两位博主的,毕竟看了别人的代码,思路就固化了。开始不知道输出是答案的两倍,除了一个2就过了。
后来想了一下,应该是重复枚举了,毕竟l最后会超过r,所以要除以2