日记 我是耐断更王。
至于我为啥又开始更了呢?因为我发现,不把解题思路记下来真的会忘。
因为今天要把所有的没写解题思路的题补上,所以就不分上午下午的了。
我们看到“恰好”两个字,就想到先推“至少”的情况,再用二项式反演的式子推到“恰好”。
设 f m f_m f m 表示至少有 m m m 个 2023
的方案数。我们钦定有 m m m 个 2023
,再用插板法 ,在这些 2023
的缝里插入那些乱七八糟的数。因为插入的时候会再凑出一些 2023
,所以是“至少”。那么,在 m m m 个 2023
中插入 n − 4 m n - 4m n − 4 m 个数的方案是
f m = ( ( n − 4 m ) + ( m + 1 ) − 1 ( n − 4 m ) − 1 ) f_m = \binom{(n - 4m) + (m + 1) - 1}{(n - 4m) - 1} f m = ( ( n − 4 m ) − 1 ( n − 4 m ) + ( m + 1 ) − 1 ) 设 g m g_m g m 表示恰好有 m m m 个 2023
的方案数,那么有:
f m = ∑ i = m n ( i m ) g i f_m = \sum\limits_{i = m}^{n}\binom{i}{m}g_i f m = i = m ∑ n ( m i ) g i 根据二项式反演公式,我们得到:
g m = ∑ i = m n ( − 1 ) i − m ( i m ) f i g_m = \sum\limits_{i = m}^{n}(-1)^{i - m}\binom{i}{m}f_i g m = i = m ∑ n ( − 1 ) i − m ( m i ) f i 那么我们就求得了 g m g_m g m ,就是答案。时间复杂度 O ( n ) \mathcal{O}(n) O ( n )
还是由“至少”转到“恰好”。
设 f k f_{k} f k 表示钦定有 k k k 个相同元素的情况,那么,剩下的 n − k n - k n − k 个元素能够组成 2 n − k 2^{n - k} 2 n − k 个集合,而,这 2 n − k 2^{n - k} 2 n − k 个集合又能够再组成 2 2 n − k 2^{2^{n - k}} 2 2 n − k 个集合。那么显然有
f k = ( n k ) 2 2 n − k f_{k} = \binom{n}{k}2^{2^{n - k}} f k = ( k n ) 2 2 n − k 设 g k g_{k} g k 表示恰好有 k k k 个相同元素的情况,那么有:
f k = ∑ i = k n ( i k ) g i f_{k} = \sum\limits_{i = k}^{n}\binom{i}{k}g_{i} f k = i = k ∑ n ( k i ) g i 反演一下得到:
g k = ∑ i = k n ( − 1 ) i − k ( i k ) f i g_{k} = \sum\limits_{i = k}^{n}(-1)^{i - k}\binom{i}{k}f_{i} g k = i = k ∑ n ( − 1 ) i − k ( k i ) f i 我们就得到了 g k g_{k} g k 。时间复杂度 O ( n ) \mathcal{O}(n) O ( n ) 。
我们先考虑没有限制的情况:d p i dp_{i} d p i 表示没有限制的情况下买价格为 i i i 的物品的方案数,容易发现这就是一个完全背包,可以在 O ( v a l ) \mathcal{O}(val) O ( v a l ) 的复杂度下预处理,其中 v a l val v a l 表示最大价格。然后接下来考虑限制的情况。发现正着考虑不超过限制的情况不太好做,正难则反 。 我们考虑超过限制的情况。超过限制就是第 i i i 个硬币强制选 d i + 1 d_{i} + 1 d i + 1 个,剩下的依然随便选,那么情况数就是 d p s − ( d i + 1 ) × c i dp_{s - (d_{i} + 1) \times c_{i}} d p s − ( d i + 1 ) × c i ,答案就要减去 ∑ i = 1 4 d p s − ( d i + 1 ) × c i \sum\limits_{i = 1}^{4}dp_{s - (d_{i} + 1) \times c_{i}} i = 1 ∑ 4 d p s − ( d i + 1 ) × c i 。这是单个硬币超出限制的情况,如果有多个硬币,就得请出我们的容斥原理了。但是,容斥原理的公式要求任意两个集合的交集和并集大小相等,这很明显不相等啊,我们又发现:只有 4 4 4 种硬币,那我们直接枚举不就行了吗?无非就是带一个 16 16 16 的常数嘛。
核心代码:
1
2
3
4
5
6
7
8
9
10
int ans = dp[s]; //dp是预处理好的完全背包
for ( int k = 1 ; k < ( 1 << 4 ); k ++ )
{
int tmp = s;
for ( int i = 0 ; i < 4 ; i ++ )
if (k & ( 1 << i))
tmp -= (d[i] + 1 ) * c[i];
if (tmp >= 0 )
ans += ( __builtin_popcount (k) & - 1 : 1 ) * dp[tmp]; //容斥
}
还是一道很板的二项式反演。首先设 f i f_{i} f i 表示至少有 i i i 个同学没有拿到特产的方案数,那么有:
f i = ( n i ) × ∏ j m ( a j + n − i − 1 n − i − 1 ) f_{i} = \binom{n}{i} \times \prod\limits_{j}^{m}\binom{a_{j} + n - i - 1}{n - i - 1} f i = ( i n ) × j ∏ m ( n − i − 1 a j + n − i − 1 ) 后面那坨表示将 a j a_{j} a j 个物品分成 n − i n - i n − i 个可空集的方案数,而前面的是因为我们并没有钦定哪几个人没有,所以要乘一个在 n n n 个人里面选 i i i 个的方案数。
接下来我们开始反演。设 g i g_{i} g i 表示正好有 i i i 个人没有,那么有反演公式:
g i = ∑ j = i n ( − 1 ) j − i ( j i ) f j g_{i} = \sum\limits_{j = i}^{n}(-1)^{j - i}\binom{j}{i}f_{j} g i = j = i ∑ n ( − 1 ) j − i ( i j ) f j 而我们要让每一个人都拿到,答案就是 g 0 g_{0} g 0 。这样,我们就做完了。时间复杂度 O ( n ) \mathcal{O}(n) O ( n )
发现考虑不同的方案数有点难,正难则反 。 依然先考虑“至少”。我们设 c n t i cnt_i c n t i 为至少有 i i i 位相同的方案数。这个可以用哈希求解。我们设哈希函数:
1
2
3
4
int hsh ( char ch ){ return isdigit (ch) ? ch - '0' : ch - 'a' + 10 ;}
int hsh ( char ch1 , char ch2 ){ return hsh (ch1) * 36 + hsh (ch2);}
int hsh ( char ch1 , char ch2 , char ch3 )
{ return hsh (ch1) * 36 * 36 + hsh (ch2) * 36 + hsh (ch3);}
分别用于求解一个字符,两个字符,三个字符的哈希值。很明显,这个哈希函数生成的哈希值不会超过 6 × 10 4 6 \times 10 ^ 4 6 × 1 0 4 。那么我们记录 t m p i tmp_{i} t m p i 表示有多少个字符序列的哈希值是 i i i ,然后要求解方案数呢,就相当于求解“在 t m p i tmp_{i} t m p i 个元素里随便取两个不同元素的方案数”,很明显是 t m p i × ( t m p i − 1 ) 2 \frac{tmp_{i} \times (tmp_{i} - 1)}{2} 2 t m p i × ( t m p i − 1 ) 。最后,我们求得了至少有 i i i 个元素相同的方案数,因为最多有 4 4 4 个元素相同,所以我们直接暴力容斥就行。
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
for ( int x = 1 ; x <= 4 ; x ++ ) //一个字符相同的
{
memset (tmp, 0 ,sizeof tmp);
for ( int i = 1 ; i <= n; i ++ )
tmp[ hsh (s[i][x])] ++ ;
for ( int i = 0 ; i <= 6 e 4 ; i ++ )
cnt[ 1 ] += (tmp[i] * (tmp[i] - 1 )) >> 1 ;
}
for ( int x = 1 ; x <= 4 ; x ++ ) //两个字符相同
{
for ( int y = x + 1 ; y <= 4 ; y ++ )
{
memset (tmp, 0 ,sizeof tmp);
for ( int i = 1 ; i <= n; i ++ )
tmp[ hsh (s[i][x],s[i][y])] ++ ;
for ( int i = 0 ; i <= 6 e 4 ; i ++ )
cnt[ 2 ] += (tmp[i] * (tmp[i] - 1 )) >> 1 ;
}
}
for ( int x = 1 ; x <= 4 ; x ++ ) //三个字符相同
{
for ( int y = x + 1 ; y <= 4 ; y ++ )
{
for ( int z = y + 1 ; z <= 4 ; z ++ )
{
memset (tmp, 0 ,sizeof tmp);
for ( int i = 1 ; i <= n; i ++ )
tmp[ hsh (s[i][x],s[i][y],s[i][z])] ++ ;
for ( int i = 0 ; i <= 6 e 4 ; i ++ )
cnt[ 3 ] += (tmp[i] * (tmp[i] - 1 )) >> 1 ;
}
}
}
//以下是暴力容斥
ans[ 3 ] = cnt[ 3 ];
ans[ 2 ] = cnt[ 2 ] - 3 * ans[ 3 ];
ans[ 1 ] = cnt[ 1 ] - ans[ 2 ] * 2 - ans[ 3 ] * 3 ;
ans[ 0 ] = ((n * (n - 1 )) >> 1 ) - ans[ 1 ] - ans[ 2 ] - ans[ 3 ];
printf ( " %lld " ,ans[ 4 - d]); //由于求解的是相同的,所以不同的就是4 - d个
依然是正难则反+二项式反演 演都不带演
还是从“至少”做起。设 f i f_{i} f i 表示至少有 i i i 个位置相同,g i g_{i} g i 表示正好 i i i 个位置相同。那么有反演:
f i = ∑ j = n m ( j n ) g j ⟺ g i = ∑ j = n m ( − 1 ) i − n ( j n ) f j f_{i} = \sum\limits_{j = n}^{m}\binom{j}{n}g_{j} \Longleftrightarrow g_{i} = \sum\limits_{j = n}^{m}(-1)^{i - n}\binom{j}{n}f_{j} f i = j = n ∑ m ( n j ) g j ⟺ g i = j = n ∑ m ( − 1 ) i − n ( n j ) f j 我们的答案就是 g 0 g_{0} g 0
现在的问题就在于怎么求 f i f_{i} f i 。发现初始数组的顺序对于答案来说没有影响,那么我们就记录每种颜色的数量并去重,然后开始 dp。设 d p i , j dp_{i,j} d p i , j 表示循环到第 i i i 个颜色,钦定有 j j j 个元素相同的方案数。那么有
d p i , j = ∑ k = 0 min ( c n t i , t m p ) d p i − 1 , j − k × ( c n t i k ) × ( t m p − j c n t i − k ) dp_{i,j} = \sum\limits_{k = 0}^{\min(cnt_{i},tmp)}dp_{i - 1,j - k} \times \binom{cnt_{i}}{k} \times \binom{tmp - j}{cnt_{i} - k} d p i , j = k = 0 ∑ m i n ( c n t i , t m p ) d p i − 1 , j − k × ( k c n t i ) × ( c n t i − k t m p − j ) 很明显,f i = d p m , i f_{i} = dp_{m,i} f i = d p m , i ,其中 m m m 表示颜色总数。然后我们就得出了答案,时间复杂度为 O ( n 2 ) \mathcal{O}(n^2) O ( n 2 ) 。
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
sort (a + 1 ,a + n + 1 );
int m = unique (a + 1 ,a + n + 1 ) - a - 1 ,tmp = 0 ;
dp[ 0 ][ 0 ] = 1 ;
for ( int i = 1 ; i <= m; i ++ )
{
tmp += cnt[a[i]];
for ( int j = 0 ; j <= tmp; j ++ )
for ( int k = 0 ; k <= min (j,cnt[a[i]]); k ++ )
dp[i][j] = (dp[i][j] + dp[i - 1 ][j - k] * c (tmp - j,cnt[a[i]] - k) % mod * c (cnt[a[i]],k) % mod) % mod;
}
int ans = 0 ;
for ( int i = 0 ; i <= n; i ++ )
ans = ((ans + (i & 1 ? - 1 : 1 ) * dp[m][i]) % mod + mod) % mod;
我们看完题先看数据范围:1 ≤ a ≤ b ≤ 10 10 1 \le a \le b \le 10^{10} 1 ≤ a ≤ b ≤ 1 0 10 ,直接枚举肯定不现实,我们看:欸☝,数位 dp。你要是这么想,那么恭喜你,跑偏了。
直接枚举每一个数不现实,那么我就枚举每个幸运号码呗,虽然也不现实,但是好歹比直接枚举每一个快吧。枚举每一个幸运号码,然后把是它倍数的都计算一下,可以证明 10 10 10^{10} 1 0 10 范围内的幸运号码不是很多,枚举的完。然后我们不出意外的发现,他 WA 了,究其原因是有些算重了。现在就该我们容斥出场了。发现第 i i i 个属性就是能不能被第 i i i 个幸运号码整除。设第 i i i 个号码为 x x x ,那么 ∣ S i ∣ = ⌊ b x ⌋ − ⌈ a x ⌉ |S_{i}| = \lfloor \frac{b}{x} \rfloor - \lceil \frac{a}{x}\rceil ∣ S i ∣ = ⌊ x b ⌋ − ⌈ x a ⌉ ,直接套公式容斥就好了。但是这样还是过不了。我们发现当有一个幸运号码是其他幸运号码的倍数时,这个幸运号码没有贡献。 用脚趾都想的出来
注意要开 __int128
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <bits/extc++.h>
#define int __int128
#define lcm ( x , y ) (x == 0 ? y : x * y / __gcd (x,y))
using namespace std ;
void read ( int & x )
{
x = 0 ;
short f = 1 ;
char ch = getchar ();
while ( ! isdigit (ch)){f = ch == '-' ? - 1 : 1 ; ch = getchar ();}
while ( isdigit (ch)){x = x * 10 + ch - '0' ; ch = getchar ();}
x *= f;
}
void write ( int x )
{
if (x > 9 )
write (x / 10 );
putchar (x % 10 + '0' );
}
int a,b,ans;
map < vector < int >::iterator, bool> vis;
vector <int> pending,num;
void dfs1 ( int x )
{
if (x > b)
return ;
if (x)
pending. push_back (x);
dfs1 (x * 10 + 6 );
dfs1 (x * 10 + 8 );
}
void dfs2 ( vector < int >:: iterator idx , int cnt , int x )
{
if (x > b)
return ;
if (idx == num. end ())
{
if (x == 0 )
return ;
ans += (cnt & 1 ? 1 : - 1 ) * ( floor ( 1.0 * b / x) - ceil ( 1.0 * a / x) + 1 );
return ;
}
dfs2 (idx + 1 ,cnt + 1 , lcm (x, * idx));
dfs2 (idx + 1 ,cnt,x);
}
signed main ()
{
read (a), read (b);
dfs1 ( 0 );
for ( auto i = pending. begin (); i != pending. end (); i ++ )
{
if ( ! vis[i])
num. push_back ( * i);
for ( auto j = i + 1 ; j != pending. end (); j ++ )
if ( * j % * i == 0 )
vis[j] = 1 ;
}
sort (num. begin (),num. end (), greater < int >());
dfs2 (num. begin (), 0 , 0 );
write (ans);
return 0 ;
}
题解 里说:
看到题目限制不能经过给定的两个点,自然想到容斥。
至于怎么自然而然想到容斥,我也不知道。多做点题就好了。
设 d p ( a , b ) dp(a,b) d p ( a , b ) 表示从 a ( x 1 , y 1 , z 1 ) a(x_{1},y_{1},z_{1}) a ( x 1 , y 1 , z 1 ) 走到 b ( x 2 , y 2 , z 2 ) b(x_{2},y_{2},z_{2}) b ( x 2 , y 2 , z 2 ) 的方案数。设 s t ( 1 , 1 , 1 ) , e n ( n , m , w ) st(1,1,1),en(n,m,w) s t ( 1 , 1 , 1 ) , e n ( n , m , w ) ,p 1 , p 2 p_{1},p_{2} p 1 , p 2 分别为不能走到的两个点。那么根据容斥原理,有:
a n s = d p ( s t , e n ) − d p ( s t , p 1 ) × d p ( p 1 , e n ) − d p ( s t , p 2 ) × d p ( p 2 , e n ) + d p ( s t , p 1 ) × d p ( p 1 , p 2 ) × d p ( p 2 , e n ) \begin{aligned} ans & = dp(st,en) \\ & - dp(st,p_{1}) \times dp(p_{1},en) \\ & - dp(st,p_{2}) \times dp(p_{2},en) \\ & + dp(st,p_{1}) \times dp(p_{1},p_{2}) \times dp(p_{2},en) \end{aligned} an s = d p ( s t , e n ) − d p ( s t , p 1 ) × d p ( p 1 , e n ) − d p ( s t , p 2 ) × d p ( p 2 , e n ) + d p ( s t , p 1 ) × d p ( p 1 , p 2 ) × d p ( p 2 , e n ) 现在我们想:如何计算 d p ( a , b ) dp(a,b) d p ( a , b ) 。我们看,麻烦之处在于只能走质数格,考虑没有这个限制如何做。类似二维的方法:d p ( a , b ) = ( Δ x + Δ y + Δ z Δ x ) × ( Δ y + Δ z Δ y ) dp(a,b) = \binom{\Delta x + \Delta y + \Delta z}{\Delta x} \times \binom{\Delta y + \Delta z}{\Delta y} d p ( a , b ) = ( Δ x Δ x + Δ y + Δ z ) × ( Δ y Δ y + Δ z ) ,意义很好理解,这里就不说了。
现在再考虑烦人的质数限制。发现一步走多远不重要,重要的是走这么远要多少步。设 f i , j f_{i,j} f i , j 表示用 j j j 个质数走 i i i 格的方案数,那么这就是一个完全背包:
f i , j = ∑ k ∈ p r k ≤ i f i − k , j − 1 f_{i,j} = \sum\limits_{k \in pr}^{k \le i}f_{i - k,j - 1} f i , j = k ∈ p r ∑ k ≤ i f i − k , j − 1 其中 p r pr p r 表示质数集合。因为 i i i 最大只有 3000 3000 3000 ,3000 3000 3000 以内的质数也没有 1000 1000 1000 个,所以预处理的时间是可以过的。
那依据此,我们得到了:
d p ( a , b ) = ∑ i = 1 Δ x ∑ j = 1 Δ y ∑ k = 1 Δ z ( i + j + k i ) ( j + k j ) f Δ x , i f Δ y , j f Δ z , k dp(a,b) = \sum\limits_{i = 1}^{\Delta x}\sum\limits_{j = 1}^{\Delta y}\sum\limits_{k = 1}^{\Delta z}\binom{i + j + k}{i}\binom{j + k}{j}f_{\Delta x,i}f_{\Delta y,j}f_{\Delta z,k} d p ( a , b ) = i = 1 ∑ Δ x j = 1 ∑ Δ y k = 1 ∑ Δ z ( i i + j + k ) ( j j + k ) f Δ x , i f Δ y , j f Δ z , k 时间复杂度 O ( n m w ) \mathcal{O}(nmw) O ( nm w ) 。立即发生爆炸
我们看这三个 ∑ \sum ∑ 就不顺眼,想想能不能优化掉一个。 我们看能不能在枚举 i i i 的同时计算 j j j 呢?好像可以。设 s u m = i + j sum = i + j s u m = i + j ,那么有:
d p ( a , b ) = ∑ i = 0 Δ x ∑ j = 0 Δ y ∑ k = 0 Δ z ( i + j + k ) ! i ! × j ! × k ! f Δ x , i f Δ y , j f Δ z , k = ∑ i = 0 Δ x ∑ j = 0 Δ y ∑ k = 0 Δ z ( i + j + k ) ! × f Δ x , i i ! × f Δ y , j j ! × f Δ z , k k ! = ∑ s u m = 0 Δ x + Δ y ∑ i = 0 s u m f Δ x , i i ! × f Δ y , s u m − i ( s u m − i ) ! ∑ k = 0 Δ z ( s u m + k ) ! × f Δ z , k k ! \begin{aligned} dp(a,b) & = \sum\limits_{i = 0}^{\Delta x}\sum\limits_{j = 0}^{\Delta y}\sum\limits_{k = 0}^{\Delta z}\frac{(i + j + k)!}{i! \times j! \times k!}f_{\Delta x,i}f_{\Delta y,j}f_{\Delta z,k} \\ & = \sum\limits_{i = 0}^{\Delta x}\sum\limits_{j = 0}^{\Delta y}\sum\limits_{k = 0}^{\Delta z}(i + j + k)! \times \frac{f_{\Delta x,i}}{i!} \times \frac{f_{\Delta y,j}}{j!} \times \frac{f_{\Delta z,k}}{k!} \\ & = \sum\limits_{sum = 0}^{\Delta x + \Delta y}\sum\limits_{i = 0}^{sum}\frac{f_{\Delta x,i}}{i!} \times \frac{f_{\Delta y,sum - i}}{(sum - i)!}\sum\limits_{k = 0}^{\Delta z}(sum + k)! \times \frac{f_{\Delta z,k}}{k!} \end{aligned} d p ( a , b ) = i = 0 ∑ Δ x j = 0 ∑ Δ y k = 0 ∑ Δ z i ! × j ! × k ! ( i + j + k )! f Δ x , i f Δ y , j f Δ z , k = i = 0 ∑ Δ x j = 0 ∑ Δ y k = 0 ∑ Δ z ( i + j + k )! × i ! f Δ x , i × j ! f Δ y , j × k ! f Δ z , k = s u m = 0 ∑ Δ x + Δ y i = 0 ∑ s u m i ! f Δ x , i × ( s u m − i )! f Δ y , s u m − i k = 0 ∑ Δ z ( s u m + k )! × k ! f Δ z , k 时间复杂度 O ( n ( m + w ) ) \mathcal{O}(n(m + w)) O ( n ( m + w )) ,就可以过了。
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <bits/extc++.h>
#define int long long
#define Inv ( x ) binpow (x,mod - 2 )
using namespace std ;
const int maxn = 3005 ;
const int mod = 1 e 9 + 7 ;
int n,m,w;
int fac[maxn],inv[maxn];
int f[maxn][maxn];
bool ipr[maxn];
vector <int> pr;
struct node
{
int x,y,z;
}st,en,p1,p2;
int binpow ( int x , int y )
{
int ret = 1 ;
while (y)
{
if (y & 1 )
ret = ret * x % mod;
x = x * x % mod;
y >>= 1 ;
}
return ret;
}
void init ()
{
for ( int i = 2 ; i <= 3000 ; i ++ )
{
if ( ! ipr[i])
pr. push_back (i);
for ( auto j = pr. begin (); j != pr. end () && * j * i <= 3000 ; j ++ )
{
ipr[ * j * i] = 1 ;
if (i % * j == 0 )
break ;
}
}
int up = max ( max (n,m),w);
f[ 0 ][ 0 ] = 1 ;
for ( int i = 1 ; i <= up; i ++ )
for ( int j = 1 ; j <= i >> 1 ; j ++ )
for ( auto k = pr. begin (); k != pr. end () && * k <= i; k ++ )
f[i][j] = (f[i][j] + f[i - * k][j - 1 ]) % mod;
up *= 3 ;
fac[ 0 ] = 1 ;
for ( int i = 1 ; i <= up; i ++ )
fac[i] = fac[i - 1 ] * i % mod;
inv[up] = Inv (fac[up]);
for ( int i = up - 1 ; i >= 0 ; i -- )
inv[i] = inv[i + 1 ] * (i + 1 ) % mod;
}
int dp ( node x , node y )
{
int dx = y.x - x.x;
int dy = y.y - x.y;
int dz = y.z - x.z;
if (dx < 0 || dy < 0 || dz < 0 )
return 0 ;
int ret = 0 ;
for ( int sum = 0 ; sum <= (dx >> 1 ) + (dy >> 1 ); sum ++ )
{
int sum1 = 0 ;
for ( int i = 0 ; i <= sum; i ++ )
if ( int j = sum - i; i <= (dx >> 1 ) && j <= (dy >> 1 ))
sum1 = (sum1 + f[dx][i] * inv[i] % mod * f[dy][j] % mod * inv[j] % mod) % mod;
int sum2 = 0 ;
for ( int k = 0 ; k <= (dz >> 1 ); k ++ )
sum2 = (sum2 + f[dz][k] * inv[k] % mod * fac[sum + k] % mod) % mod;
ret = (ret + sum1 * sum2 % mod) % mod;
}
return ret;
}
signed main ()
{
scanf ( " %lld%lld%lld " , & n, & m, & w);
st = { 1 , 1 , 1 };
en = {n,m,w};
scanf ( " %lld%lld%lld " , & p1.x, & p1.y, & p1.z);
scanf ( " %lld%lld%lld " , & p2.x, & p2.y, & p2.z);
init ();
if (p2.x <= p1.x && p2.y <= p1.y && p2.z <= p1.z)
swap (p1, p2);
int ans1 = dp (st,en);
int ans2 = dp (st,p1) * dp (p1,en) % mod;
int ans3 = dp (st,p2) * dp (p2,en) % mod;
int ans4 = dp (st,p1) * dp (p1,p2) % mod * dp (p2,en) % mod;
int ans = (((ans1 + ans4) % mod - (ans2 + ans3) % mod) % mod + mod) % mod;
printf ( " %lld " ,ans);
return 0 ;
}