Imagine A is a NxM matrix with two basic properties
1) Each element in the matrix is distinct and lies in the range of 1<=A[i][j]<=(N*M)
2) For any two cells of the matrix, (i1,j1) and (i2,j2), if (i1^j1) > (i2^j2) then A[i1][j1] > A[i2][j2] ,where
1 ≤ i1,i2 ≤ N
1 ≤ j1,j2 ≤ M.
^ is Bitwise XOR
Given N and M , you have to calculatethe total number of matrices of size N x M which have both the properties
mentioned above.
Input format:
First line contains T, the number of test cases. 2*T lines follow with N on the first line and M on the second, representing the number of rows and columns respectively.
Output format:
Output the total number of such matrices of size N x M. Since, this answer can be large, output it modulo 10^9+7
Constraints:
1 ≤ N,M,T ≤ 1000
SAMPLE INPUT
1
2
2
SAMPLE OUTPUT
4
Explanation
The four possible matrices are:
[1 3] | [2 3] | [1 4] | [2 4]
[4 2] | [4 1] | [3 2] | [3 1]
题解: 这个题是可以纯暴力水过的,但是我感觉要是范围再大一点就不可以了,所以还是应该会点正解的。
1、有一个非常高深的办法,就是先算出来前500个,然后再然后类似二分然后算出来后面的情况总的时间复杂度就是500*500;
2、数位dp。
3、就是我写的这个二维的树状数组,但是能想到这个解决办法的人,我认为还是很厉害的,我是实在想不到。
讲道理这个东西确实厉害。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+50;
const int mod=1e9+7;
long long f[2000000],c[maxn][maxn];
vector<pair<int,int> >v[maxn];
long long ans[maxn][maxn];
struct node
{
int a,b;
}s[maxn];
void inist()
{
f[0]=1;
for(int i=1;i<=1000000;i++)
{
f[i]=(f[i-1]*(i%mod));
f[i]%=mod;
}
}
int lowbit(int x)
{
return x&-x;
}
int sum(int x,int y)
{
int ret = 0;
for(int i = x;i > 0;i -= lowbit(i))
for(int j = y;j > 0;j -= lowbit(j))
ret += c[i][j];
return ret;
}
void add(int x,int y,int val)
{
for(int i = x;i <= 1000;i += lowbit(i))
for(int j = y;j <= 1000;j += lowbit(j))
c[i][j] += val;
}
int main()
{
int t;
scanf("%d",&t);
inist();
for(int i=1;i<=t;i++) scanf("%d%d",&s[i].a,&s[i].b);
for(int i=1;i<=1000;i++)
{
for(int j=1;j<=1000;j++)
{
v[i^j].push_back(make_pair(i,j));
}
}
for(int x=0;x<=1024;x++)
{
int sz=v[x].size();
for(int j=0;j<sz;j++)
{
int a=v[x][j].first;
int b=v[x][j].second;
add(a,b,1);
}
for(int j=1;j<=t;j++)
{
ans[j][x]=sum(s[j].a,s[j].b);
}
for(int j=0;j<sz;j++)
{
int a=v[x][j].first;
int b=v[x][j].second;
add(a,b,-1);
}
}
for(int i=1;i<=t;i++)
{
for(int j=0;j<=1024;j++)
{
if(ans[i][j]==0) ans[i][j]=ans[i][j-1];
else
{
if(j>=1)
ans[i][j]=(f[ans[i][j]]*ans[i][j-1])%mod;
else ans[i][j]=(f[ans[i][j]])%mod;
}
}
printf("%lld\n",ans[i][1024]);
}
}