题目链接:https://ac.nowcoder.com/acm/contest/9699/H
题目描述:
Bobo 有一个矩形A。举行的左下角坐标是 (x1, y1),右上角坐标是 (x2, y2)。设 R(i, j) 是左下角坐标是 (0, 0),右上角坐标是 (i, j) 的矩形,Area(i, j) 是矩形 A 和矩形 R(i, j) 的并的面积。
给出 a 和 b,求:∑i=1a∑j=1bArea(i,j)除以 (109 + 7) 的余数。
输入描述:
输入文件包含多组数据,请处理到文件结束。 每组数据的第一行包含两个整数 a 和 b,第二行包含四个整数 x1, x2, y1, y2. · 1 ≤ a, b, x1, x2, y1, y2 ≤ 109 · x1 < x2 , y1 < y2 · 数据组数不超过 104
输出描述:
对于每组数据,输出一个整数,表示所求的值。
示例:
输入: 1 1 2 3 2 3 10 10 1 5 1 5 1000000000 1000000000 1 1000000000 1 1000000000 输出: 2 3725 2793
题目分析:
1,先不论题目,本题有一个要求结果 “(109 + 7) 的余数”。
因为如果mod简单的数理论上会增大算法错误但是由于巧合恰好模出相等的数,而AC的概率
而1e9+7这个数是素数,相加不爆int,相乘不爆ll。
所以由于在运算过程中说有数都可能爆ll所以在相加相乘的时候要随时余mod!
2,在算数运算符的左侧如果运算数num都是int类型而运算符右侧都是long long型时,运算符右侧运算数 num 需要 * 1LL
*1LL是为了在计算时,把int类型的变量转化为long long
,然后再赋值给long long
类型的变量
例如,long long ans = 0;
ans
是long long
类型的,
ans += num * 1LL * (num - 1) / 2;
不至于后面计算溢出,* 1LL
之后类型就转换为long long
, num变量是定义为int
类型的。
3.在写题时,看到阶乘符号,首先想到的是使用while把结果累加。
而实际上可以直接使用数列求和公式直接把结果算出来,从而降低时间复杂度。
代码:
c:
#include<cstdio> typedef long long ll; const ll mod = 1e9 + 7; ll all(ll xx, ll yy) { return xx * (xx + 1) / 2 % mod * (yy * (yy + 1) / 2 % mod) % mod; } int main() { ll a, b; ll x1, y1, x2, y2; while (~scanf("%lld %lld %lld %lld %lld %lld", &a, &b, &x1, &x2, &y1, &y2)) { ll ans = 0; ans += all(a, b) % mod; ans = (ans + a * b % mod * (x2 - x1) % mod * (y2 - y1) % mod) % mod; if (x1 < a && y1 < b) { ll x = a - x1, y = b - y1; ans = (ans + mod - all(x, y)) % mod; if (x2 < a) { ll xx = a - x2; ans = (ans + all(xx, y)) % mod; } if (y2 < b) { ll yy = b - y2; ans = (ans + all(x, yy)) % mod; if (x2 < a) { ll xx = a - x2; ans = (ans + mod - all(xx, yy)) % mod; } } } printf("%lld ", ans); } return 0; }