51nod: 1225 n%i 餘數之和
阿新 • • 發佈:2018-12-16
題意是給一個n 求 n%i 的和這個n比較大 (1e12), 所以不能直接去一個個的求
n%i 可以寫成 n - n/i * i (這裡的'/'是整除) 這樣的話我們要求的結果就是
只需要求出後面的就可以,這個可以分塊來求,從第i個數到第 n / (n / i) 個數的 的結果都是相同的,所以可以把具有相同值得分成一塊,可以直接求出這一塊的結果。
下面有java大數和c++寫的兩種程式碼,java比c++慢十倍(因為用的大數)。
程式碼java:
import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner cin = new Scanner(System.in); BigInteger n = cin.nextBigInteger();; BigInteger T1 = BigInteger.valueOf(1); BigInteger T2 = BigInteger.valueOf(2); BigInteger r = T1, ans = n.multiply(n); while(r.compareTo(n) < 0) { BigInteger l = r; BigInteger t = n.divide(r); r = n.divide(t).add(T1); BigInteger c1 = r.subtract(l); BigInteger c2 = l.add(r).subtract(T1); BigInteger temp = c1.multiply(c2).multiply(t).divide(T2); ans = ans.subtract(temp); } System.out.println(ans.mod(BigInteger.valueOf(1000000007))); } }
c++程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9+7; ll inv2 = 5e8+4; int main() { ll n; scanf("%lld", &n); ll ans1 = (n % mod) * (n % mod) % mod; ll r = 1, ans2 = 0; while (r < n) { ll l = r; ll t = n / r; r = n / t + 1; t %= mod; ll c1 = (r - l) % mod; ll c2 = (l + r - 1) % mod; ll temp = c1 * c2 % mod * t % mod * inv2 % mod; ans2 = (ans2 + temp) % mod; } ll ans = (ans1 - ans2 + mod) % mod; printf("%lld\n", ans); return 0; }