wannafly test D
题意:
给定n,m
求满足:
1.a[i][j]互不相同,且有$1<=a[i][j]<=n*m$
2.对于$a[i1][j1],a[i2][j2]$,如果有 $i1 \oplus j1 > i2 \oplus j2$,则有$a[i1][j1] > a[i2][j2]$
的矩形个数,答案取余$10^9+7$
数据组数T<=1000,且n,m <= 1000
解法:
首先注意到我们只要根据$i \oplus j$分类,计算出$cnt(x)$表示$i \oplus j = x$的$i,j$对数。
这样有答案为$\sum_{i=0}^{1024}{cnt(x)!}$
1.(雾)对于每组数据循环i,j然后cnt[i^j]++;,因为 i^j 操作很快所以AC
2.每个询问是关于(n,m)的一个二元组,考虑对n莫队分块,这样复杂度$O(T*n* \sqrt{n} + 1024*T)$
3.考虑fwt,注意到cnt = id(n)*id(m),应用fwt卷积可以$O(T*nlogn)$
1 \#include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <bitset> 5 #include <algorithm> 6 7 #define N 1010 8 #define LL long long 9 #define P 1000000007LL 10 11 using namespace std; 12 13 struct node 14 { 15 int n,m,id; 16 }a[N]; 17 18 LL fac[N*N]; 19 LL ansv[N]; 20 int cnt[2034],SIZE; 21 22 bool cmp(node a,node b) 23 { 24 if((a.n-1)/SIZE==(b.n-1)/SIZE) return a.m<b.m; 25 return a.n<b.n; 26 } 27 28 LL calc(int n,int m) 29 { 30 LL ans=1; 31 for(int i=0;i<=2000;i++) 32 ans=ans*fac[cnt[i]]%P; 33 return ans; 34 } 35 36 int main() 37 { 38 int T; 39 scanf("%d",&T); 40 for(int i=1;i<=T;i++) 41 { 42 scanf("%d%d",&a[i].n,&a[i].m); 43 a[i].id=i; 44 } 45 SIZE = 100; 46 sort(a+1,a+T+1,cmp); 47 fac[0]=1LL; 48 for(int i=1;i<N*N;i++) fac[i]=fac[i-1]*(LL)i%P; 49 int n=0,m=0; 50 for(int i=1;i<=T;i++) 51 { 52 while(n<a[i].n) 53 { 54 n++; 55 for(int j=1;j<=m;j++) 56 cnt[n^j]++; 57 } 58 while(n>a[i].n) 59 { 60 for(int j=1;j<=m;j++) 61 cnt[n^j]--; 62 n--; 63 } 64 while(m<a[i].m) 65 { 66 m++; 67 for(int j=1;j<=n;j++) 68 cnt[j^m]++; 69 } 70 while(m>a[i].m) 71 { 72 for(int j=1;j<=n;j++) 73 cnt[j^m]--; 74 m--; 75 } 76 ansv[a[i].id] = calc(n,m); 77 } 78 for(int i=1;i<=T;i++) cout << ansv[i] << endl; 79 return 0; 80 }