A-pairs
题意:
给出n个x轴上的坐标点,问有多少对<a,b>使得第a个点与第b个点间的距离不超过k。
分析:
由于给出的点是x轴上的点,那么可以先按x坐标的大小对点进行排序,之后问题便转化成了对于第i个点,右边有多少个点与它的距离不超过k,然后累加即可。直接遍历判断的话,复杂度是o(n^2),会超时,必须要进行优化,可以想到如果找到了右边距离i点不超过k的最远点j,那么此时满足条件的对数为j-i,即不用将所有满足条件的点遍历完了。继续优化,如何快速的找出满足条件的右边最远点j,考虑到所有点已经是排好序了的,所以可以使用二分法快速定位。
源代码:
#include <cstdio>
#include <algorithm>
#define LL __int64
using namespace std;
int data[100005];
int main()
{
//freopen("sample.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--)
{
int n, k;
scanf("%d%d", &n, &k);
for(int i=0; i<n; ++i)
{
scanf("%d", &data[i]);
}
LL ans = 0;
sort(data, data+n);
for(int i=0; i<n; ++i)
{
int l = i+1;
int r = n-1;
// 二分查找
while(l <= r)
{
int mid = l+(r-l)/2;
if(data[mid]-data[i] > k)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
ans += r-i;
}
printf("%I64d\n", ans);
}
return 0;
}
B-beautiful number
题意:
问[L,R]的范围内,有多少个数字是漂亮数字,即满足从高位到低位上的数值依次递减,且任意一个高位上的数值模上低位上的数值都要等于零。
分析:
注意到L、R的范围是10^9,规定时间是1s,看起来时间比较紧,所以考虑能否先将10^9内的漂亮数字离线预处理出来,然后再判断即可。预处理漂亮数字可以这么做,因为这种数字的每一位都要满足给出的条件,所以可以构造每一位从而找出所有的漂亮数字,具体构造方法的话,可以使用深搜,从最高位开始,然后判断是否满足条件即可,事实上这种数字很少,不会搜得很多的。需要注意的是,判断依次递减好弄,但是判断任意高位模低位等于零似乎麻烦,但是其实只需要当前位和上一高位即可,因为如果这一位可以被上一位整除,那么一定能被前面所有位整除,因为前面所有位都是判断过的,所以在这种情况下,当前位是前面所有位的因子。
源代码:
#include<cstdio>
int data[1000000], sz;
int tmp[100];
void solve(int dep, int num)
{
if(dep > 9) return;
// 将满足条件的数字保存下来
data[sz++] = num;
for(int i=1; i<10; ++i)
{
// 判断条件
if(tmp[dep-1] < i) continue;
if(tmp[dep-1]%i != 0) continue;
tmp[dep] = i;
solve(dep+1, num*10+i);
}
}
int main()
{
// 离线构造10^9内的所有漂亮数字
for(int i=1; i<10; ++i)
{
tmp[0] = i;
solve(1, i);
}
int T, L, R, ans;
scanf("%d", &T);
while(T--)
{
ans = 0;
scanf("%d%d", &L, &R);
for(int i=0; i<sz; ++i)
{
if(L<=data[i] && data[i]<=R) ++ans;
}
printf("%d\n", ans);
}
return 0;
}