版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/88647379
题目大意:
分析:
对于一个数
的贡献,其实就是
*
然后直接
的枚举
对所有的
预先
然后后面利用
_
去找对应的位置
这个位置预存
然后
预处理一下
时间复杂度好像是
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define N 2005
using namespace std;
typedef long long ll;
const int mo = 1e9 + 7;
int a[N*N], b[N*N], id[N*N][5], mi[N], orz[N], n, m;
ll ans;
void read(int &x)
{
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
int main()
{
scanf("%d %d", &n, &m);
mi[0] = 1; for (int i = 1; i <= m; i++) mi[i] = (ll)mi[i - 1] * n % mo;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
read(a[n * (i - 1) + j]), b[n * (i - 1) + j] = a[n * (i - 1) + j];
sort(b + 1, b + n * m + 1);
int size = unique(b + 1, b + n * m + 1) - b - 1;
int x, num;
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
x = a[n * (i - 1) + j];
num = lower_bound(b + 1, b + size + 1, x) - b;
if (!id[num][3]) id[num][2] = 1;
if (id[num][1] != i)
{
if (id[num][3]) id[num][2] = (ll)id[num][2] * (n - id[num][4]) % mo;
id[num][4] = 0, id[num][3] += 1, id[num][1] = i;
}
id[num][4]++;
ans = (ans + (ll)id[num][2] * mi[m - id[num][3]] % mo * x % mo) % mo;
}
}
ans = ans % mo;
printf("%lld\n", ans);
}