P2424 约数和
题目链接
思路:
首先很容易想到算 i 的贡献,比如 [ L , R] = [5 , 15] , 那么数字 3 在这段区间的贡献c次数就是 15 / 3 - (5 - 1) / 3 = 4
所以可以:
int l , r; cin >> l >> r; l --; int ans = 0; for(int i = 1 ; i <= r ; i ++){ ans += i * (r / i - (l / i)); } cout << ans << '\n';
但是这个只能拿60,由于 r 太大了,所以:
B部分我没找到规律,直接用二分找了。
代码:
#include<bits/stdc++.h> using namespace std; #define int long long #define ll long long #define pb push_back const int maxn = 1e6 + 10; const int mod = 998244353; using namespace std; int cal(int l , int r) { if(l > r)swap(l , r); int a = (r + 1) * r / 2; int b = (l - 1) * l / 2; return a - b; } int Get(int left , int up , int value) { int l = left; int r = up; while(l < r){ int mid = (l + r) >> 1; if(up / mid != value){ r = mid - 1; } else{ l = mid; if((l + r >> 1) == l){ if(up / r == value) l = r; else r = l; } } } return l; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int l , r; cin >> l >> r; l --; int ans1 = 0 , ans2 = 0; for(int i = 1 ; i <= r ; i ++){ int now = r / i; int re = Get(i , r , now); ans1 += cal(re , i) * now; i = re; } for(int i = 1 ; i <= l ; i ++){ int now = l / i; int re = Get(i , l , now); ans2 += cal(re , i) * now; i = re; } cout << ans1 - ans2 << '\n'; return 0; } /* 12 / 1 = 12 12 / 2 = 6 12 / 3 = 4 12 / 4 = 3 12 / 5~6 = 2 12 / 7 ~ 12 = 1 9 / 1 = 9 9 / 2 = 4 9 / 3 = 3 9 / 4 = 2 9 / 5~9 = 1 4 / 1 = 4 4 / 2 = 2 4 / 3~4 = 1 */