1. 程式人生 > >(dp)CodeForces - 300D Painting Square

(dp)CodeForces - 300D Painting Square

clas 預處理 action 技術 sign std ces span ecif

Vasily the bear has got a large square white table of n rows and n columns. The table has got a black border around this table.

技術分享 The example of the initial table at n = 5.

Vasily the bear wants to paint his square table in exactly k moves. Each move is sequence of actions:

  1. The bear chooses some square inside his table. At that the square must have a black border painted around it. Also, the square shouldn‘t contain a black cell. The number of cells in the square shouldn‘t be less than 2.
  2. The bear chooses some row and some column inside the chosen square. Then he paints each cell of this row and this column inside the chosen square. After that the rectangles, formed by the square‘s border and the newly painted cells, must be squares of a non-zero area.
技術分享
An example of correct painting at n
= 7 и k = 2.

The bear already knows numbers n and k. Help him — find the number of ways to paint the square in exactly k moves. Two ways to paint are called distinct if the resulting tables will differ in at least one cell. As the answer can be rather large, print the remainder after dividing it by 7340033.

Input

The first line contains integer q (1?≤?q?≤?105) — the number of test data.

Each of the following q lines contains two integers n and k (1?≤?n?≤?109,?0?≤?k?≤?1000) — the size of the initial table and the number of moves for the corresponding test.

Output

For each test from the input print the answer to the problem modulo 7340033. Print the answers to the tests in the order in which the tests are given in the input.

Example

Input
8
1 0
1 1
3 0
3 1
2 0
2 1
3 2
7 2
Output
1
0
1
1
1
0
0
4

Note

All possible painting ways for the test n?=?7 and k?=?2 are:

技術分享

這個題不仔細讀題容易讀錯,首先必須分成正方形而非矩形,其次some row some column 指的是某一條行、列。

明確是分成正方形後顯然可知,只有邊長為奇數的的正方形才可以繼續分下去。顯然對於某邊長x的正方形,每次只分其左上角的(初始時分整體),最多分 x二進制下末尾1的個數次。很自然的就可以想到一種遞推。

用dp[i][j]表示邊長為“i”(二進制下尾數1的個數)的正方形分j次的情況數。

dp[i][x]=∑(x1+x2+x3+x4=x xi>=0)dp[i-1][x1]*dp[i-1][x2]*dp[i-1][x3]*dp[i-1][x4]

這樣一個∑還是比較麻煩,可以通過預處理(類似倍增的想法)先用an[x]表示對兩個邊長為i-1的正方向一共操作x次的情況數,顯然an[x]=Σ(x1+x2=x,xi>=0)dp[i-1]*[x1]*dp[i-1][x2]

則dp[i][x]=Σ(x1+x2=x,xi>=0)an[x1]*an[x2] ,降低了原本n^3的復雜度為n^2(雖然n最大也不過30,影響可以忽略不計)

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <queue>
 8 #include <set>
 9 #include <map>
10 #include <list>
11 #include <vector>
12 #include <stack>
13 #define mp make_pair
14 //#define P make_pair
15 #define MIN(a,b) (a>b?b:a)
16 //#define MAX(a,b) (a>b?a:b)
17 typedef long long ll;
18 typedef unsigned long long ull;
19 const int MAX=1e3+5;
20 const int MAX_V=2e4+5;
21 const ll INF=2e11+5;
22 const double M=4e18;
23 using namespace std;
24 //const int MOD=1e9+7;
25 const ll MOD=7340033;
26 typedef pair<ll,int> pii;
27 const double eps=0.000000001;
28 #define rank rankk
29 int q,n,k,mi;
30 ll dp[31][MAX],num[MAX];
31 int main()
32 {
33     scanf("%d",&q);
34     dp[0][0]=1LL;
35     for(int i=1;i<=30;i++)
36     {
37         dp[i][0]=1LL;
38         memset(num,0,sizeof(num));
39         for(int s=0;s<=1000;s++)
40             for(int j=0;j<=1000-s;j++)
41                 num[s+j]=(num[s+j]+dp[i-1][s]*dp[i-1][j]%MOD)%MOD;
42         for(int s=0;s<1000;s++)
43             for(int j=0;j<1000-s;j++)
44                 dp[i][s+j+1]=(dp[i][s+j+1]+num[s]*num[j]%MOD)%MOD;
45     }
46     while(q--)
47     {
48         scanf("%d%d",&n,&k);
49         mi=0;
50         while(n>1&&(n&1))
51             n>>=1,++mi;
52         printf("%I64d\n",dp[mi][k]);
53     }
54     return 0;
55 }

(dp)CodeForces - 300D Painting Square