codechef Flooring(数学题)

题意:

i = 1 N i 4 N i % M

思路:

  • 考试的时候看到,实在是一点思路都没有,主要是不知道四次方和有简便公式,主要是太菜了。

  • 这是题解思路: N i 的不同的取值只有 2 N 种,且相同的值是连续的,所以只要对值相同的连续的i求四次方和就可以了。这个靠YY还勉强YY的出来,至于证明…然后还有一个用于取模的性质: a / b % c = a % ( b c ) / b ,公式中除30就可以很方便的做了。

  • 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;
}

公式还是挺有用的,取模的那个,在除较小的数取模时可以不用逆元(与膜数不用互质了),但这里要求整除。
四次方和公式的确可以现场推,只不过用了整整两张纸而已

猜你喜欢

转载自blog.csdn.net/xyyxyyx/article/details/81433916