mxqz卡常
  • 板块灌水区
  • 楼主Stinger
  • 当前回复1
  • 已保存回复1
  • 发布时间2021/5/30 19:23
  • 上次更新2023/11/4 22:29:19
查看原帖
mxqz卡常
361308
Stinger楼主2021/5/30 19:23

题目:输入 n,m,kn,m,k,再输入一个 nnmm 列矩阵,求有多少条线路从矩阵左上角到右下角的线路经过的所有数乘积超过 kk,线路只能向下/右走。

就是一个根号分治优化 dp 做法,然后就 T 了。

#include <cstdio>
#include <cmath>
#include <cstring>
#define int long long

inline int min(const int x, const int y) {return x < y ? x : y;}
const int mod = 1e9 + 7;
int mp[1000005], mp2[1000005], cnt;
int a[305][305], f[2][305][2005];

signed main() {
	int n, m, k;
	scanf("%lld%lld%lld", &n, &m, &k);
	for (int i = 1; i <= n; ++ i)
	for (int j = 1; j <= m; ++ j) scanf("%lld", &a[i][j]);
	for (int i = 1; i <= k; ++ i)
		if (i == 1 || ceil(1.0 * k / i) != ceil(1.0 * k / (i - 1)))
			mp[i] = ++ cnt, mp2[cnt] = i;
	f[1][1][mp[(int)ceil(1.0 * k / a[1][1])]] = 1;
	for (register int i = 1, cur = 1; i <= n; ++ i, cur ^= 1) {
		memset(f[cur ^ 1], 0, sizeof f[0]);
		for (register int j = 1; j <= m; ++ j)
		for (register int K = 1; K <= cnt; ++ K) {
			if (i < n) {
				register int x = min(k, (k + mp2[K] - 1) / mp2[K] * a[i + 1][j]);
				x = mp[(k + x - 1) / x];
				f[cur ^ 1][j][x] = (f[cur ^ 1][j][x] + f[cur][j][K]) % mod;
			}
			if (j < m) {
				register int x = min(k, (k + mp2[K] - 1) / mp2[K] * a[i][j + 1]);
				x = mp[(k + x - 1) / x];
				f[cur][j + 1][x] = (f[cur][j + 1][x] + f[cur][j][K]) % mod;
			}
		}
	}
	printf("%lld\n", f[n & 1][m][1]);
}
···
2021/5/30 19:23
加载中...