ZOJ - 3955 Saddle Point 每个值对答案的贡献
2017-12-03 20:06
246 查看
题意:
给定n*m的 矩阵,
选择一行或者若干行,一列或者若干列,构成新的矩阵,问这个矩阵中,满足某个元素是本行最小本列最大的这个性质的所有元素的个数
思路:
题中说了,所有的矩阵的可能性 有 (2^n - 1) * (2^m - 1)中,显然没法枚举;
所以 我们考虑某一个元素,会在那个矩阵中出现,也就是算这个元素满足上面性质时 对答案的贡献值是多少;
这样我们可以找到一个值推一下,他在本行中满足最小这个条件,那本行中比他大的所有值 所在的那一列跟他都可以组合形成矩阵,
同理在这一列中比他小的的所有值所在的哪一行也可以跟他任意组合 形成矩阵
加个快速幂
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define PI acos(-1.0)
#define in freopen("in.txt", "r", stdin)
#define out freopen("out.txt", "w", stdout)
#define kuaidian ios::sync_with_stdio(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6, maxd = 1000 + 7;
const ll mod = 1e9 + 7;
const int INF = 0x7f7f7f7f;
int n, m;
int a[maxd][maxd];
int b[maxd][maxd], c[maxd][maxd];
ll pow_(ll x, int n) {
ll ans = 1;
while(n) {
if(n&1) ans = (ans*x) % mod;;
x = (x * x) % mod;
n /= 2;
}
return ans;
}
void solve() {
int anss = 0;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
int t1 = m - (upper_bound(b[i]+1, b[i]+1+m, a[i][j]) - (b[i]+1) );
int t2 = (lower_bound(c[j]+1, c[j]+1+n, a[i][j]) - (c[j]+1) );
anss = (anss + (pow_(2, t1))*(pow_(2, t2)) ) % mod;
}
}
cout << anss << endl;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
scanf("%d", &a[i][j]);
b[i][j] = a[i][j];
c[j][i] = a[i][j];
}
}
for(int i = 1; i <= n; ++i) {
sort(b[i]+1, b[i]+1+m);
}
for(int i = 1; i <= m; ++i) {
sort(c[i]+1, c[i]+1+n);
}
solve();
}
return 0;
}
给定n*m的 矩阵,
选择一行或者若干行,一列或者若干列,构成新的矩阵,问这个矩阵中,满足某个元素是本行最小本列最大的这个性质的所有元素的个数
思路:
题中说了,所有的矩阵的可能性 有 (2^n - 1) * (2^m - 1)中,显然没法枚举;
所以 我们考虑某一个元素,会在那个矩阵中出现,也就是算这个元素满足上面性质时 对答案的贡献值是多少;
这样我们可以找到一个值推一下,他在本行中满足最小这个条件,那本行中比他大的所有值 所在的那一列跟他都可以组合形成矩阵,
同理在这一列中比他小的的所有值所在的哪一行也可以跟他任意组合 形成矩阵
加个快速幂
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define PI acos(-1.0)
#define in freopen("in.txt", "r", stdin)
#define out freopen("out.txt", "w", stdout)
#define kuaidian ios::sync_with_stdio(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6, maxd = 1000 + 7;
const ll mod = 1e9 + 7;
const int INF = 0x7f7f7f7f;
int n, m;
int a[maxd][maxd];
int b[maxd][maxd], c[maxd][maxd];
ll pow_(ll x, int n) {
ll ans = 1;
while(n) {
if(n&1) ans = (ans*x) % mod;;
x = (x * x) % mod;
n /= 2;
}
return ans;
}
void solve() {
int anss = 0;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
int t1 = m - (upper_bound(b[i]+1, b[i]+1+m, a[i][j]) - (b[i]+1) );
int t2 = (lower_bound(c[j]+1, c[j]+1+n, a[i][j]) - (c[j]+1) );
anss = (anss + (pow_(2, t1))*(pow_(2, t2)) ) % mod;
}
}
cout << anss << endl;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
scanf("%d", &a[i][j]);
b[i][j] = a[i][j];
c[j][i] = a[i][j];
}
}
for(int i = 1; i <= n; ++i) {
sort(b[i]+1, b[i]+1+m);
}
for(int i = 1; i <= m; ++i) {
sort(c[i]+1, c[i]+1+n);
}
solve();
}
return 0;
}
相关文章推荐
- ZOJ-3955-Saddle Point【17th浙大校赛】
- ZOJ 3872 计算对答案的贡献
- ZOJ - 3955Saddle Point(思维)
- ZOJ 3955 Saddle Point (排序/二分/树状数组)
- ZOJ 3955 Saddle Point (树状数组)
- ZOJ 3955 Saddle Point
- zoj 2971 答案
- 会让每个女孩子哭的答案
- zoj 3955 Saddle Point
- zoj 2100 Seeding 【DFS 判断是否能经过每个点一次遍历完整个图】
- 对于每个复杂的问题都会有一个简单但不准确的答案
- 对于每个复杂的问题都会有一个简单但不准确的答案
- zoj 3955 Saddle Point
- 会让每个女孩感动的想哭的答案
- [ZOJ 2112] Dynamic Rankings [块状链表+二分答案+二分查找]
- zoj 3955 Saddle Point
- zoj 3955 Saddle Point
- ZOJ Saddle Point 数学思维题
- CodeForces - 358D dp 每个数取走的贡献与相邻的数有关,状态转移
- Codeforces Round #336 (Div. 2) B. Hamming Distance Sum 计算答案贡献+前缀和