前言:又只写出一题,感觉要提前退役了呢
A.水
B.二维计数题
题目大意:
二维平面上给你由 n 条 y = y i y = y_i y=yi 的直线和 m条 x = x j x = x_j x=xj的直线.问你所有构成的子矩阵的面积之和.( n , m ≤ 1 e 5 n,m \leq 1e5 n,m≤1e5)
题目思路:
之前做过单纯的求子矩阵的个数之和.这次变成求子矩阵的面积之和.就没推出来了…很烦.所以让我们严格的来推导一波吧.
1.朴素计算式: a n s = ∑ 1 ≤ i < j ≤ n ∑ 1 ≤ k < l ≤ m ( x j − x i ) ∗ ( y l − y k ) ans = \sum_{1 \leq i < j \leq n}\sum_{1 \leq k < l \leq m} (x_j-x_i)* (y_l-y_k) ans=∑1≤i<j≤n∑1≤k<l≤m(xj−xi)∗(yl−yk)
复杂度: O ( n 4 ) O(n^4) O(n4)
2.观察到两项独立,则有: a n s = ∑ 1 ≤ i < j ≤ n ( x j − x i ) ∗ ∑ 1 ≤ k < l ≤ m ( y l − y k ) ans = \sum_{1 \leq i < j \leq n} (x_j-x_i)* \sum_{1 \leq k < l \leq m} (y_l-y_k) ans=∑1≤i<j≤n(xj−xi)∗∑1≤k<l≤m(yl−yk)
复杂度: O ( n 2 ) O(n^2) O(n2)
考虑两项的意义: ∑ 1 ≤ i < j ≤ n ( x j − x i ) \sum_{1 \leq i < j \leq n} (x_j-x_i) ∑1≤i<j≤n(xj−xi)就是在数组 x x x上求解所有连续子段和.
那么考虑每一个相邻的段 x i − x i + 1 x_i-x_{i + 1} xi−xi+1它对答案的贡献为: x i x_i xi左侧的点个数乘上 x i + 1 x_{i+1} xi+1右侧的点个数.
所以上述式子转化为: ∑ i = 1 n − 1 ( x i − x i + 1 ) ∗ i ∗ ( n − i ) \sum_{i=1}^{n-1} (x_i-x_{i+1}) * i*(n - i) ∑i=1n−1(xi−xi+1)∗i∗(n−i) ,对y求解一样的方法.
复杂度为: O ( n ) O(n) O(n)
后话:其实它的实际含义也很好理解:一个矩阵其实就是X方向上确定两个点 + Y方向上确定两个点构成的四元组.
C.究极思维题
题目大意:
有两个只含AB的字符串S,T(
∣
S
∣
,
∣
T
∣
≤
1
e
5
|S|,|T| \leq 1e5
∣S∣,∣T∣≤1e5).你有两种操作:1.将A转换为BB 或 将B转化为AA. 2.删除AAA/BBB.
现在有Q(
Q
≤
1
e
5
Q \leq 1e5
Q≤1e5)次询问,每次询问你S和T的一段子字符串.问你这两个子字符串是否能够通过任意次上述操作使其相等.
题目思路:
朴素思路:
思考操作的一般性质:可逆性和相邻交换性
这两个性质很容易看出来: AB <-> AAA <-> BA.
其实根据题目也是要往这方面想.因为Q这么大,我们肯定是 O ( 1 ) O(1) O(1)判定.
观察出这两个特性之后,我们可以知道其实只需要关注两字符串中的A,B个数即可.
又发现一性质:可以凭空增加一个 ‘AB’. 即: B -> AA -> ABB .相当于A,B各增加一个.
所以我们可以先对一种字符 A/B 将他们调整到一致.再讨论另一个.
然而另一个字符只有相差 3的倍数时,才能调整到一致.
所以维护前缀和.差分判断一下即可.
巧妙思路:Hash
将A 看做1, B 看做 2.
则:
A -> BB 等价于 1 -> 4
B -> AA 等价于 2 -> 2
AAA -> 空 等价于 3 -> 0
BBB -> 空 等价于 6 -> 0.
所以容易发现: 这四种操作都无法改变 字符串数值和 在 模3 意义下的 值.且可以构造出无限大的数值和 并且根据上一个方法得到的 可逆性 和 相邻交换性 .就可直接判断 两子串数值和 模3 意义下 的值是否相等.
D.思维,dp
题目大意:
一个无限长的序列,满足以下两个规则:
1.
[
n
,
+
∞
)
[n,+\infty)
[n,+∞)范围内的数全等
2.对于一个数
a
i
a_i
ai,
[
i
+
1
,
i
+
a
i
]
[i+1,i+a_i]
[i+1,i+ai]范围内的数全等.
现在问你长度为n( n ≤ 1 e 6 n\leq1e6 n≤1e6)能够产生多少个不同的序列.
题目思路:
不难发现本题关键点:当存在两个相邻的非1项时,从这两项开始后面的值就已经确定了.
形如: [ a , b , b , b . . . , b ] [a,b,b,b...,b] [a,b,b,b...,b]
不难利用动态规划,从后往前dp.
1.当第i位填 x = 1 x=1 x=1时, f i ← f i + 1 f_i \leftarrow f_{i+1} fi←fi+1
2.当第i位填 x ∈ [ 2 , n − i ] x \in [2,n-i] x∈[2,n−i]时, f i ← ∑ k = i + 3 n f k f_i \leftarrow \sum_{k = i + 3}^{n}f_k fi←∑k=i+3nfk
3.当第i位填 x ∈ [ n − i + 1 , n ] x \in [n-i+1,n] x∈[n−i+1,n]时, f i ← i f_i \leftarrow i fi←i
4当第i位和第i+1位填非1数时, f i ← ( n − 1 ) 2 f_i \leftarrow (n - 1)^2 fi←(n−1)2
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
using namespace std;
const int maxn = 1e6 + 4;
const int mod = 1e9 + 7;
ll dp[maxn] , aft[maxn];
int main()
{
ios::sync_with_stdio(false);
ll n; cin >> n;
if (n == 1){
cout << 1 << endl;
return 0;
}
dp[n] = n;
dp[n - 1] = n * n % mod;
aft[n + 1] = 1;
aft[n] = dp[n] + aft[n + 1];
aft[n - 1] = (aft[n] + dp[n - 1]) % mod;
//aft[n + 1] = 1;
for (ll i = n - 2 ; i >= 1 ; i--){
// 填x = [2,n - i],后面跟x个1
dp[i] = (dp[i] + aft[i + 3]) % mod;
// 填写一个1
dp[i] = (dp[i] + dp[i + 1]) % mod;
// 填x = [n - i + 1 , n], 后面跟 n - i 个1
dp[i] = (dp[i] + i) % mod;
// 前后两项都填非1数
dp[i] = (dp[i] + 1ll*(n - 1ll)*(n - 1ll)%mod) % mod;
aft[i] = (aft[i + 1] + dp[i]) % mod;
}
cout << dp[1] << endl;
return 0;
}