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 }
View Code

 

posted @ 2017-03-09 15:25  lawyer'  阅读(111)  评论(0编辑  收藏  举报