problem
对于一个数对
(a,b)
,如果满足
a%b=a/b
,则称这个数对为“好的数对”。
如果
a⩽n,b⩽n
,那么有多少对数对是“好的数对”呢?
1⩽n⩽1e9
Sample Input
5
8
3
65
Sample Output
3
7
1
131
思路1
表面意思 ∑na=1∑nb=1[a%b=a/b] ,这里 a/b=⌊ab⌋
由于
a=ab∗b+a%b
可得
a=(a%b)∗(b+1)
那我只要枚举
a
和它的因子d,凡是满足
令
t=a%b
显然t < b,枚举
t
[1,n-1]则满足
。对于每一个t,累加b的个数 nt−1−t 即为答案。时间复杂度 O(n) ,会TLE。代码如下:
ll ans=0;
for(int t=1;t<n;++t){//枚举t
if((n/t-1)>t){//这时候才有意义 因为t=a%b , t < b <= n/t -1
ans+=(n/t-1-t);
}
}
cout<<ans<<endl;
再进一步思考,为什么要做这个限制呢?因为这是b的上限,肯定在大于t的情况下才有意义
if((n/t-1)>t)
观察 (b+1)∗t⩽n 又t < b则 (t+1)∗t<n ,枚举更大的t就无意义了,即省去了上面的if。时间复杂度 O(n√)
代码示例
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(false);
ll n;
while(cin>>n)
{
ll ans=0;
for(int t=1;t*(t+1)<n;++t) ans+=(n/t-1-t);
cout<<ans<<endl;
}
return 0;
}
思路2
直接对a的因子进行考虑,由于因子成对出现(完全平方数单独考虑)发现以 a√ 为界限,右面的因子都有对应的b满足题意
于是考虑求出1~n区间内所有数的因子(出现一次),但时间限制,不能去枚举每个a。从反面考虑因子可能情况,即1是哪些数的因子,2是哪些数的因子,3是哪些数的因子…… 即先求出 ⌊n1⌋+⌊n2⌋+⌊n3⌋+⌊n4⌋+......+⌊nn⌋
然后ans-3是因为a=1 a=2时无符合题意,而其有3个因子于是减去。
下面两行是考虑完全平方数和t*(t+1)两种特殊情况
for(int i=2;i*i<=n;++i) --ans;
for(int i=2;i*(i+1)<=n;++i) ans-=2;
最后ans/2即为结果(右半边)
求 ⌊n1⌋+⌊n2⌋+⌊n3⌋+⌊n4⌋+......+⌊nn⌋ 的方法
ans=0;
int l=1;
for(;l<=n;++l)
{
int r=n/(n/l);
ans+=1LL*(r-l+1)*(n/l);
l=r;
}
代码示例
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e9;
int n;
long long ans=0;
int main()
{
while(scanf("%d",&n)!=EOF)
{
ans=0;
int l=1;
for(;l<=n;++l)
{
int r=n/(n/l);
cout<<"l:"<<l<<" r: "<<r<<endl;
cout<<1LL*(r-l+1)*(n/l)<<endl;
ans+=1LL*(r-l+1)*(n/l);
l=r;
}
ans-=3;
for(int i=2;i*i<=n;++i) --ans;
for(int i=2;i*(i+1)<=n;++i) ans-=2;
printf("%lld\n",ans/2);
}
return 0;
}