1. 程式人生 > 實用技巧 >2020.11.23 考試題解

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;
}