文章

4

粉丝

271

获赞

6

访问

9.7k

头像
注意这题有坑,要避免重复计算
P1814 复旦大学2018年机试
发布于2023年3月24日 19:53
阅读数 2.5k

比如说30

1出现次数30

2出现次数15

3出现次数10

4出现次数7

5出现次数6

6出现次数5

7出现次数4

8-10出现次数3

11-15出现次数2

16-30出现次数1

对于每个i小于根号n,其本身出现n/i次,出现i次的数从a/(i+1)+1到a/i,可以等差数列求和,所以一开始写了这样的代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,ans;
ll sum(ll l,ll r){
    return (l+r)*(r-l+1)/2;
}
int main(){
    cin>>a;
    ans=0;
    for (ll i=1;i*i<=a;i++){
        ans+=i*(a/i);
        ans+=i*sum(a/(i+1)+1,a/i);
    }
    cout<<ans<<endl;
}

当然这样是错的,因为比如11这个数据

1*11

2*5

3*3

(4+5)*2

(6+7+8+9+10+11)*1

明显3*3被算了两次

所以所有存在i符合n/i=i的数都要减掉i*i

也就是k^2到k^2+k-1之间的所有数

所以修改了代码,就能过了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,ans;
ll sum(ll l,ll r){
    return (l+r)*(r-l+1)/2;
}
int main(){
    cin>>a;
    ans=0;
    for (ll i=1;i*i<=a;i++){
        ans+=i*(a/i);
        ans+=i*sum(a/(i+1)+1,a/i);
    }
    ll t=sqrt(a);
    if (t*(t+1)>...
登录查看完整内容


登录后发布评论

暂无评论,来抢沙发