链接:
https://www.nowcoder.com/acm/contest/81/A
题目描述
在三维空间中,平面 x = 0, y = 0, z = 0,以及平面 x + y + z = K 围成了一个三棱锥。
整天与整数打交道的小明希望知道这个三棱锥内、上整点的数目。
他觉得数量可能很多,所以答案需要对给定的 M 取模。
整天与整数打交道的小明希望知道这个三棱锥内、上整点的数目。
他觉得数量可能很多,所以答案需要对给定的 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;
}
参考资料
《算法竞赛入门经典(第二版)》刘汝佳