寒武纪测试赛1 C(取模和整除的性质 经典)

problem

对于一个数对 (a,b) ,如果满足 a%b=a/b ,则称这个数对为“好的数对”。
如果 an,bn ,那么有多少对数对是“好的数对”呢?

1n1e9

pdf题面

Sample Input

5

8

3

65

Sample Output

3

7

1

131

思路1

表面意思 na=1nb=1[a%b=a/b] ,这里 a/b=ab

由于 a=abb+a%b 可得 a=(a%b)(b+1) 那我只要枚举 a 和它的因子d,凡是满足a=(a%(d1))d 的因子 d d1即为对应的b。时间复杂度 O(nlogn) ,会TLE

t=a%b 显然t < b,枚举 t [1,n-1]则满足(b+1)tn的b的个数可求,即 t<bnt1

。对于每一个t,累加b的个数 nt1t 即为答案。时间复杂度 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)tn 又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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值