Handbook是H星人的一家社交网络。Handbook中共有N名用户,其中第i名用户的年龄是Ai。
根据H星人的文化传统,用户i不会给用户j发送好友请求当且仅当:
1. Aj < 1/8 * Ai + 8 或者
2. Aj > 8 * Ai + 8 或者
3. Ai < 88888 且 Aj > 88888
其他情况用户i都会给用户j发送好友请求。
你能求出Handbook总计会有多少好友请求吗?
Input
第一行一个整数N。
第二行N个整数A1, A2, ... AN。
对于30%的数据,1 ≤ N ≤ 100
对于100%的数据,1 ≤ N ≤ 100000, 1 ≤ Ai ≤ 100000
Output
输出Handbook中好友请求的总数
Sample Input
2 10 80
Sample Output
1
原本我直接用模拟来走,找出符合要求的但是wa了,搜题解后发现那是个假算法。。。
正确思路应该是找符合要求的区间;;;
可行区间
1:9~16
2:9~24
9:10~80
10:10~88
11:10~96
16:10~136
17:11~144
11110:1397~88888
11112:1397~88888
88888:11103~88888
88889:88888~100000
100000:88888~100000
找左右临界值就是找规律,注意最后要判断自己是不是在区间里面,毕竟自己不能给自己发邮件。。。。(第一次没考虑到)
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#define pi 3.1415926
#define inf 0x3f3f3f3f
using namespace std;
const long long mod = 1e9 + 7;
#define ll long long
#define MAXN 1000005
//char s[MAXN],t[MAXN];
int a[MAXN];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
} sort(a, a + n);
long long ans = 0;
for (int i = 0; i < n; i++)
{
int v1;
if (a[i] / 8 * 8 == a[i])
{
v1 = a[i] / 8 + 8;
}
else
{
v1 = a[i] / 8 + 9;
}
int v2 = 8 * a[i] + 8;
if (a[i] < 88888)
{
v2 = min(v2, 88888);
}
int sign = upper_bound(a, a + n, v2) - lower_bound(a, a + n, v1);
if (a + i >= lower_bound(a, a + n, v1) && a + i < upper_bound(a, a + n, v2))sign -= 1; //自己在区间里面
sign = max(0, sign);
ans += sign;
}
cout << ans << endl;
return 0;
}