504 字
3 分钟
BZOJ 2956 模积和
题目
一道有点复杂的数论分块。
公式推导
所求即为:
先不管的情况:
然后在讨论的情况:
然后就可以愉快的分块了。
代码
/************************************************************** Problem: 2956 User: Dicer Language: C++ Result: Accepted Time:184 ms Memory:1292 kb****************************************************************/
#include<bits/stdc++.h>#define rep(i, a, b) for(int i = (a); i <= (int)(b); ++i)#define per(i, a, b) for(int i = (a); i >= (int)(b); --i)#define debug(x) cout << #x << ' ' << x << endl;using namespace std;
typedef long long ll;const int MAXN = 1e5 + 7;const int MOD = 19940417;const int INV = 3323403;
ll cal(ll n){ ll ans = 0; for(ll i = 1, j; i <= n; i = j + 1){ j = n / ( n / i); ans += (i + j) * (j - i + 1) / 2 * (n / i); ans %= MOD; } return ans;}ll cal(ll n, ll k){ ll ans = 0; for(ll i = 1, j; i <= k; i = j + 1){ j = min(k, n / ( n / i)); ans += (i + j) * (j - i + 1) / 2 * (n / i); ans %= MOD; } return ans;}
ll sum(ll n){ return n * (n + 1) % MOD * (2 * n + 1) % MOD * INV % MOD;}
ll cal(ll n, ll m, ll k){ ll ans = 0; for(ll i = 1, j; i <= k; i = j + 1){ j = min(k, min(n / (n / i), m / (m / i))); ans += (sum(j) - sum(i-1)) * (n/i) % MOD * (m/i) % MOD; ans %= MOD; } return ans;}
ll mul(ll a, ll b){ a %= MOD; b %= MOD; return a * b % MOD;}
int main(){ ll n, m, k; scanf("%lld%lld", &n, &m); k = min(n, m); long long ans = 0; ans += mul(n * n, m * m); ans -= mul(n * n, cal(m)); ans -= mul(m * m, cal(n)); ans += mul(cal(n), cal(m)); ans = ((ans % MOD) + MOD) % MOD; ans -= mul(k, n * m); ans += mul(n, cal(m, k)); ans += mul(m, cal(n, k)); ans -= cal(n, m, k); ans = ((ans % MOD) + MOD) % MOD; printf("%lld\n", ans); return 0;}