标签:
给两个数n, m. 求n%1+n%2+.......+n%m的值。
首先, n%i = n-n/i*i, 那么原式转化为n*m-sigma(i:1 to m)(n/i*i)。
然后我们可以发现 1/4 = 2/4 = 3/4 = 0, 4/4 = 5/4 = 6/4 = 7/4 = 1. 所以可以将这些结果分成很多块, 按块算结果。
注意计算过程中时刻避免爆longlong。
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const ll mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; vector <pair<ll, ll> > v; ll getsum(ll a, ll b) { if((b-a)%2==0) { return ((b-a)/2%mod)*((a+b+1)%mod)%mod; } return ((a+b+1)/2%mod)*((b-a)%mod)%mod; } int main() { ll n, m; cin>>n>>m; for(ll i = 1; i*i<=n; i++) { ll tmp = n/i; v.pb(mk(i, tmp)); if(tmp != i) { v.pb(mk(tmp, i)); } } v.pb(mk(0, 0)); sort(v.begin(), v.end()); ll ans = (n%mod)*(m%mod)%mod; int i; for(i = 1; i<v.size()&&m>=v[i].fi; i++) { ans = (ans- getsum(v[i-1].fi, v[i].fi)%mod*(v[i].se%mod)%mod+mod)%mod; } if(m<n) ans = (ans - getsum(v[i-1].fi, m)%mod*(v[i].se%mod)%mod+mod)%mod; cout<<ans<<endl; return 0; }
codeforces 616E. Sum of Remainders 数学
标签:
原文地址:http://www.cnblogs.com/yohaha/p/5211104.html