2020.11.23 考试题解

T1

题目描述:

求满足下列条件的二元组(a,b)的个数
a mod b = b div a
1<=a,b<=n

样例输入:

10

样例输出:

21

数据范围:

对于 10%的数据: \(n\) <= \(10^3\)

对于 20%的数据: \(n\) <= \(10^5\)

对于 30%的数据: \(n\) <= \(10^7\)

对于 40%的数据: \(n\) <= \(10^{12}\)

当经过手模样例和一些自己出的样例之后,可以发现,\(a\)肯定不能等于\(b\),那么就分为两种情况讨论:

<1>:

\(a<b\)时,\(a\;mod\;b=a\),即\(\left\lfloor\dfrac{b}{a}\right\rfloor=a\) 。显然,\(a\)小于\(\sqrt{n}\),直接等差数列\(O(1)\)就出即可,需特判一下\(\sqrt{n}\)

<2>:

\(a>b\)时,\(\left\lfloor\dfrac{b}{a}\right\rfloor=0\)
即为

\[\sum\limits_{a,b} {a\;mod\;b=0} \]

考虑转换成枚举\(b\),即为

\[\sum\limits_{b} {(\left\lfloor\dfrac{n}{b}\right\rfloor-1)} \]

减一是为了除去\(a=b\)的情况。
转化之后即为

\[\sum\limits_{b} {\left\lfloor\dfrac{n}{b}\right\rfloor}-n \]

即为下底函数分块,可将取值相同的一块一起处理。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+7;
#define il inline
#define vocaloid(v) (v>='0'&&v<='9')
#define ll long long
template <typename T>
il void read(T &x)
{
	x=0;char v=getchar();
	while(!vocaloid(v)) v=getchar();
	while(vocaloid(v)) {x=(x<<1)+(x<<3)+v-'0';v=getchar();}
}
template <typename T>
il void write(T x)
{
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
bool flag=1;
ll n,ans,a[5000007],cnt;
int main()
{
	freopen("diyiti.in","r",stdin);
	freopen("diyiti.out","w",stdout);
	read(n);
	ll mid=sqrt(n);
	for(int i=1;i<=mid;i++) a[++cnt]=i;
	int now=cnt;
	for(int i=now;i>=1;i--) a[++cnt]=n/a[i];
	for(int i=1;i<=cnt;i++) 
		ans+=(a[i]-a[i-1])*(n/a[i]);
	ans-=n;
	ans+=(mid-1)*mid/2-1;
	ans+=min(mid,n-mid*mid+1);
	write(ans);putchar('\n');
	return 0;
}
posted @ 2020-12-04 16:55  初雫  阅读(131)  评论(0)    收藏  举报