Wannafly 挑战赛14 A题题解

链接: https://www.nowcoder.com/acm/contest/81/A

题目描述

在三维空间中,平面 x = 0, y = 0, z = 0,以及平面 x + y + z = K 围成了一个三棱锥。
整天与整数打交道的小明希望知道这个三棱锥内、上整点的数目。
他觉得数量可能很多,所以答案需要对给定的 M 取模。

输入描述:

输入有 1 ≤ T ≤ 105 组数据。
每组数据中,输入两个整数 0 ≤ K ≤ 109 + 7, 1 ≤ M ≤ 109 + 7,意义如题目描述。

输出描述:

对于每组数据,输出一个整数,为三棱锥内、上整点的数目对 M 取模。

首先我们可以推理出三棱锥x+y+x = n和 x+y+x = n-1之间整数点的个数相差(2+n)*(n-1)/2+1个 ,我们整理这个式子:

n*(n+1) / 2,那么我们就知道x+y+z = n中包含的点的个数为它的前(n+1)项求和:

1*2+2*3+3*4+......+n*(n+1) + (n+1) * (n+2)= (n+1) * (n+2) * (n+3)/3

最终我们的式子为:

(n+1) * (n+2) * (n+3) / 6

前面我们乘法取余有可能会超出long long 范围,那么我们这里需要对整体的除法进行取余操作,这里不能保证取的余数是质数,所以不能用费马小定理求的逆元,那么我们就可以下面一个公式,不管mod是不是质数...

(a/b) % c = (a % (b*c)) /b

所以最终的程序为:

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
#define ll long long

using namespace std;
ll K,M;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
       scanf("%lld%lld",&K,&M);
       printf("%lld\n",((K+1) * (K+2) % (6 *M) * (K+3) % (6 * M) /6 ) % M);
    }
}

参考博客:

https://blog.csdn.net/zy691357966/article/details/44836667

大数取模算法

比如数字12345进行取模运算,那么我们可以将12345转换为 (((1*10+2)*10+3)*10+4)*10+5,然后用前面的公式,每步取模

实现:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;
string str;
int main()
{
    int mod;
    cin>>str;
    cin>>mod;
    int len = str.size();
    int ans = 0;
    for(int i =0 ;i < len; i++)
    {
        ans = int(ans * 10 + str[i] - '0') % mod;
    }
    cout<<ans<<endl;
}

参考资料

《算法竞赛入门经典(第二版)》刘汝佳

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值