NOI2013 Day2
2015-08-03 08:12
429 查看
NOI2013 Day2
矩阵游戏
题目描述:设矩阵\(F\)求\(F
[m](mod (10^9+7))\)
solution:
这题可以求通项解决。
设\(X_i=F[i][m]\),
\((a-1)X_1=a^{m-1}((a-1)+b)-b\)
令\(P=10^9+7\),\(P\)是公认的质数,所以运用费马小定理:
\(a^{P-1} \equiv 1 (mod P)\)
设\(m-1=kP+z\),则\(a^{m-1} \equiv a^z(mod P)\)
算出右式,然后再用费马小定理处理除法,求出\(X_1\)
\((a-1)X_{i+1}=a^{m-1}((cX+d)(a-1)+b)-b\)
化简得:
\((a-1)X_{i+1}=a^{m-1}(a-1)cX+a^{m-1}((a-1)d+b)-b\)
形如:\((a-1)X_{i+1}=AX_i+B\)
求通项。求出\(X_n\)
这题也可以用矩阵乘法,将矩阵乘法的二进制变成十进制就好了。
时间复杂度:\(O(n)\)
书法家
题目描述:在一个\(n\)行\(m\)列的矩阵中,每个格有对应的值,现在矩阵中画\('NOI'\),下面给出三个书法字的定义:1、 \(’N’\)由若干 (\(\geq 3\)) 个边平行于坐标轴的矩形组成,设由\(K\)个矩形组成(标号\(1 ~ K\)),第\(i\)个矩形的左下角\(方格\)坐标设为\((L_i, B_i)\),右上角坐标设为\((R_i, T_i)\),要求满足:
a) \(L_i \leq R_i,B_i \leq T_i\)
b) 对任意\(1 < i \leq K\),有\(L_i= R_{i−1} + 1\);
c) 对任意\(3 \leq i < K\),有\(B_{i-1}− 1 \leq T_i \leq T_{i−1}\),\(B_i \leq B_{i−1}\);
d) \(B_2 > B_1, T_2 = T_1, B_{K−1} = B_K, T_{K-1} < T_K\);
2、 \(’O’\)由一个大矩形\(A\),挖去一个小矩形\(B\)得到, 这两个矩形的边都平行于坐标轴。 设大矩形 A 左下角的方格坐标为 \((u , v)\), 长为\(W\), 宽为\(H\) , 则小矩形 B 满足左下角方格坐标为\((u + 1, v + 1)\), 长 \(W − 2\),宽\(H − 2\)。 要
求满足:
a) \(W ≥ 3, H ≥ 3\)
b) \(u > R_K + 1\)
3、 \(’I’\)为\(3\)个边平行于坐标轴的从下到上的实心矩形组成,从下到上依次标号为\(1,2,3\),第\(i\)个矩形的左下角格子坐标设为\((P_i, Q_i)\),右上角格子坐标设为\((G_i, H_i)\),要求满足:
a) \(P_i \leq G_i, Q_i \leq H_i\)
b) \(P_1 = P_3 > u + W, G_1 = G_3\)
c) \(Q_1 = H_1 = Q_2 − 1, H_2 + 1 = Q_3 = H_3\)
d) \(P_1 < P_2 \leq G2 < G1\)
求\(‘NOI'\)覆盖的格子的值的和的最大值。
solution:
从左到右dp,\(N,O,I\)各分成三个阶段,相邻之间有空列,再加两个阶段。\(f[i][j][k]\)表示到第\(i\)个阶段,上界为\(j\),下界为\(k\)的最大值。转移方程有点烦,直接上代码。
时间复杂度:\(O(11mn^2)\)
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <ctime> #include <cmath> #include <deque> #include <queue> #include <vector> #include <map> #include <complex> using namespace std; const int maxn=160; const int maxm=510; const int oo=int(1e9); typedef int arr[maxn][maxm]; int n, m, ans; int a[maxn][maxm], sum[maxn][maxm]; int f[2][12][maxn][maxn], g[12][maxn][maxn]; void init() { scanf("%d%d", &n, &m); for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) scanf("%d", &a[i][j]); for (int j=1; j<=m; ++j) for (int i=1; i<=n; ++i) sum[i][j]=sum[i-1][j]+a[i][j]; } void calc_g() { for (int i=1; i<=n; ++i) for (int j=n; j>=i; --j) g[1][i][j]=max(g[1][i][j+1], f[0][1][i][j+1]); for (int j=1; j<=n; ++j) for (int i=1; i<=j; ++i) g[2][i][j]=max(g[2][i-1][j], f[0][2][i][j]); for (int i=1; i<=n; ++i) { g[3][i][i-1]=g[2][i-1][i-1]; for (int j=i; j<=n; ++j) g[3][i][j]=max(g[3][i][j-1], g[2][i][j]); } for (int j=1; j<=n; ++j) for (int i=j; i>=1; --i) g[4][i][j]=max(g[4][i+1][j], f[0][2][i+1][j]); } void solve() { for (int k=1; k<=11; ++k) for (int i=0; i<=n+1; ++i) for (int j=0; j<=n+1; ++j) f[0][k][i][j]=g[k][i][j]=-oo; ans=-oo; for (int i=1; i<=m; ++i) { calc_g(); f[1][4][1][1]=f[0][4][1][1]; f[1][8][1][1]=f[0][8][1][1]; for (int j=1; j<=n; ++j) for (int k=j; k<=n; ++k) { int tmps=sum[k][i]-sum[j-1][i]; int tmpa=a[j][i]+a[k][i]; //N: f[1][1][j][k]=max(f[0][1][j][k], 0)+tmps; f[1][2][j][k]=max(g[1][j][k], g[3][j][k])+tmps; f[1][3][j][k]=max(g[4][j][k], f[0][3][j][k])+tmps; f[1][4][1][1]=max(f[1][4][1][1], f[0][3][j][k]); //O: if (j+1<k)**注意题目** { f[1][5][j][k]=f[0][4][1][1]+tmps; f[1][6][j][k]=max(f[0][5][j][k], f[0][6][j][k])+tmpa; f[1][7][j][k]=f[0][6][j][k]+tmps; f[1][8][1][1]=max(f[1][8][1][1], f[0][7][j][k]); } //I: if (j+1<k)**注意题目** { f[1][9][j][k]=max(f[0][8][1][1], f[0][9][j][k])+tmpa; f[1][10][j][k]=max(f[0][9][j][k], f[0][10][j][k])+tmps; f[1][11][j][k]=max(f[0][10][j][k], f[0][11][j][k])+tmpa; ans=max(ans, f[1][11][j][k]); } } for (int j=1; j<=n; ++j) for (int k=j; k<=n; ++k) for (int p=1; p<=11; ++p) { f[0][p][j][k]=f[1][p][j][k]; f[1][p][j][k]=-oo; } } } int main() { freopen("penman.in", "r", stdin); freopen("penman.out", "w", stdout); init(); solve(); printf("%d\n", ans); return 0; }
快餐店
题目描述:给出一个只有一个环的连通图,保证环上的点数大于等于\(3\),求一个点(边上或点)到最远的点最近,求这一距离。solution:
环上的点的子树求直径更新答案,然后求出子树深度作为该点的点权。
枚举快餐店在那一条边\((i)\),环上的点分成了离左端点近,和离右端点近,求出离左端点近的,边权加点权最远的点\((P_1)\)右端点亦然\((P_2)\),求出\(W=P_1->P_2(经i的路径边权)+P_1点权+P_2点权\),若\(W/2\),即路径中点在\(i\)上,则用\(W/2\)更新答案,否则左端点和右端点更新答案(因为要求快餐店在\(i\)上)
至于如何求最远点,按某一时针枚举边,左边和右边的单调性是不变的,因为只是多了一条边和少了一条边,所以可以用单调队列维护。
时间复杂度:\(O(n)\)
相关文章推荐
- Skewness
- 用户和用户组的学习
- OC连载四-----Foundation框架——字典、日期、异常
- ios--c DAY_3
- myeclipse无法新建jsp页面
- C:进制
- (笔记)鼠标移动到一个 元素上所触发的事件
- 黑马程序员——自学java基础课程第二…
- 【bzoj1079】【SCOI2008】【着色方案】
- hibernate一对多等情况关联查询效率低的解决方法
- 素数筛法
- 【Unity游戏开发之五】游戏目录结构之最佳实践和优化
- 素数筛法
- Linux 桌面领域的八大最新潮流
- Linux 桌面领域的八大最新潮流
- POJ 2251 Dungeon Master
- HDOJ~~A+B Problem
- DFS BestCoder Round #49 ($) 1001 Untitled
- BC - Untitled
- 精通iOS