题意:
求 ∑ i = 1 N i 4 ⌊ N i ⌋ % M \sum_{i=1}^Ni^4\lfloor \frac{N}{i}\rfloor \%M ∑i=1Ni4⌊iN⌋%M
思路:
-
考试的时候看到,实在是一点思路都没有,
主要是不知道四次方和有简便公式,主要是太菜了。 -
这是题解思路: ⌊ N i ⌋ \lfloor \frac{N}{i}\rfloor ⌊iN⌋的不同的取值只有 2 ∗ N 2*\sqrt{N} 2∗N种,且相同的值是连续的,所以只要对值相同的连续的i求四次方和就可以了。这个靠YY还勉强YY的出来,至于证明…然后还有一个用于取模的性质: a / b % c = a % ( b ∗ c ) / b a/b\%c = a\%(b*c) / b a/b%c=a%(b∗c)/b,公式中除30就可以很方便的做了。
-
517 517 517:四次方和公式考场上随便推推就好了
最后贴上代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
int T, n, m;
int l, r, sum;
int GETSUM(int x)
{//四次方和公式
return ( x * ( x + 1 ) % m * ( 2 * x + 1 ) % m * ( 3 * x * x % m + 3 * x - 1 ) % m + m ) % m;
}
main()
{
m = 1e9+7;
// cout << GETSUM(7)/30-GETSUM(3)/30 << endl;
// cout << pow(4, 4)+pow(5, 4)+pow(6, 4)+pow(7, 4) << endl;
scanf("%lld", &T);
while (T--){
scanf("%lld%lld", &n, &m);
sum = 0;
m *= 30;//取模用的公式
for (int ans = 1; ; ans = n/r){
// cout << ans << "!" << endl;
l = n/ans;
r = n/(ans+1);
// cout << l << " " << r << endl;
sum = ( sum + ( ( GETSUM(l%m) - GETSUM(r%m) ) % m + m )% m * ans % m ) % m;
if (r == 0) break;
}
// cout << sum << endl;
sum /= 30;
printf("%lld\n", sum);
}
return 0;
}
公式还是挺有用的,取模的那个,在除较小的数取模时可以不用逆元(与膜数不用互质了),但这里要求整除。
四次方和公式的确可以现场推,只不过用了整整两张纸而已