2023大厂真题提交网址(含题解):
www.CodeFun2000.com(http://101.43.147.120/)
最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。
题目大意:
让你计算:
∑
i
=
x
1
x
2
∑
j
=
y
1
y
2
(
⌊
i
x
1
⌋
+
⌊
x
2
i
⌋
+
⌊
j
y
1
⌋
+
⌊
y
2
j
⌋
)
2
\sum_{i=x_{1}}^{x_{2}} \sum_{j=y_{1}}^{y_{2}}\left(\left\lfloor\frac{i}{x_{1}}\right\rfloor+\left\lfloor\frac{x_{2}}{i}\right\rfloor+\left\lfloor\frac{j}{y_{1}}\right\rfloor+\left\lfloor\frac{y_{2}}{j}\right\rfloor\right)^{2}
∑i=x1x2∑j=y1y2(⌊x1i⌋+⌊ix2⌋+⌊y1j⌋+⌊jy2⌋)2.
x 1 , y 1 , x 2 , y 2 ≤ 1 e 9 x1,y1,x2,y2 \leq 1e9 x1,y1,x2,y2≤1e9.
题目思路:
展开直接算:
令
a
=
第一部分
,
b
=
第二部分
,
c
=
第三部分
,
d
=
第四部分
a=第一部分,b=第二部分,c=第三部分,d=第四部分
a=第一部分,b=第二部分,c=第三部分,d=第四部分
通过化简可得:
=
∑
∑
a
2
+
b
2
+
c
2
+
d
2
+
2
(
a
b
+
a
c
+
a
d
+
b
c
+
b
d
+
c
d
)
=\sum\sum a^2+b^2+c^2+d^2+2(ab+ac+ad+bc+bd+cd)
=∑∑a2+b2+c2+d2+2(ab+ac+ad+bc+bd+cd).
∑ ∑ a 2 = d y ∗ ∑ a 2 \sum\sum a^2=dy*\sum a^2 ∑∑a2=dy∗∑a2. 直接分倍数段计算,然后还要算一个前n项平方的和
∑ ∑ b 2 = d y ∗ ∑ b 2 \sum\sum b^2=dy*\sum b^2 ∑∑b2=dy∗∑b2. 整除分块.
c , d 类似 c,d类似 c,d类似
后面一大坨,难点在 a ∗ b 和 c ∗ d a*b和c*d a∗b和c∗d部分.
∑ ∑ a ∗ b = d y ∗ ∑ a ∗ b \sum\sum a*b=dy*\sum a*b ∑∑a∗b=dy∗∑a∗b. 还是整除分块,
设本块的值为 x x x,块的左右端点为 [ L , R ] [L,R] [L,R],差分计算一下 r e s = ∑ i = L R ⌊ i x 1 ⌋ res=\sum_{i=L}^{R}\lfloor\frac{i}{x_1}\rfloor res=∑i=LR⌊x1i⌋.本块的贡献即为 x ∗ r e s x*res x∗res.
其他的项直接乘起来即可.
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
int a[maxn];
ll ksm (ll a , ll b){ ll ans = 1 , base = a;
while (b){if (b & 1) ans = ans * base % mod;b >>= 1;base = base * base % mod;}return ans;}
ll inv6 = ksm(6 , mod - 2);
ll inv2 = ksm(2 , mod - 2);
ll x1 , x2 , y1 , y2;
ll calc (ll n)
{
return n * (n + 1) % mod * inv2 % mod;
}
ll calc2 (ll n)
{
return n * (n + 1) % mod * ((2 * n + 1) % mod) % mod * inv6 %mod;
}
ll cal_i_x1_2 (ll x1 , ll x2)
{
ll rest = x2 % x1 + 1;
ll up = x2 / x1;
// [1 , up - 1] 每个出现 x1次
ll ans = calc2(up - 1) * x1 % mod;
// up 出现 rest次
ans = (ans + rest * up %mod * up % mod) % mod;
return ans;
}
ll cal_x2_i_2 (ll x1 , ll x2){
ll ans = 0;
for (ll l = x1 , r ; l <= x2 ; l = r + 1){
r = x2 / (x2 / l);
ll v = x2 / l;
// [l , r] 都是 v
ans = (ans + (r - l + 1) * v % mod * v % mod) % mod;
}
return ans;
}
ll cal_i_x1 (ll x1 , ll x2)
{
ll rest = x2 % x1 + 1;
ll up = x2 / x1;
// [1 , up - 1] 每个出现 x1次
ll ans = calc(up - 1) * x1 % mod;
// up 出现 rest次
ans = (ans + rest * up %mod) % mod;
return ans;
}
ll cal_ab (ll x1 , ll x2)
{
ll ans = 0;
for (ll l = x1 , r ; l <= x2 ; l = r + 1){
r = x2 / (x2 / l);
ll v = x2 / l;
ll f = cal_i_x1(x1 , r) - cal_i_x1(x1 , l - 1);
f = (f + mod) % mod;
ans = (ans + v * f%mod) % mod;
}
return ans;
}
ll cal_x2_i (ll x1 , ll x2)
{
ll ans = 0;
for (ll l = x1 , r ; l <= x2 ; l = r + 1){
r = x2 / (x2 / l);
ll v = x2 / l;
ans = (ans + v * (r - l + 1)%mod) % mod;
}
return ans;
}
ll solve ()
{
ll a , b , c , d;
ll dx = x2 - x1 + 1 , dy = y2 - y1 + 1;
a = cal_i_x1(x1 , x2);
b = cal_x2_i(x1 , x2);
c = cal_i_x1(y1 , y2);
d = cal_x2_i(y1 , y2);
vector<ll> ans;
ans.pb(dy * cal_i_x1_2(x1 , x2)%mod);
ans.pb(dy * cal_x2_i_2(x1 , x2)%mod);
ans.pb(dx * cal_i_x1_2(y1 , y2)%mod);
ans.pb(dx * cal_x2_i_2(y1 , y2)%mod);
ans.pb(dy * cal_ab(x1 , x2)%mod);
ans.pb(a * c % mod);
ans.pb(a * d % mod);
ans.pb(b * c % mod);
ans.pb(b * d % mod);
ans.pb(dx * cal_ab(y1 , y2)%mod);
ans.pb(dy * cal_ab(x1 , x2)%mod);
ans.pb(a * c % mod);
ans.pb(a * d % mod);
ans.pb(b * c % mod);
ans.pb(b * d % mod);
ans.pb(dx * cal_ab(y1 , y2)%mod);
ll res = 0;
for (auto &g : ans) res = (res + g) % mod;
return res;
}
int main()
{
ios::sync_with_stdio(false);
int t; cin >> t;
while (t--){
cin >> x1 >> x2 >> y1 >> y2;
cout << solve() << endl;
}
return 0;
}