Atcoder Grand Contest 013E - Placing Squares

Problem Statement

Joisino has a bar of length N, which has M marks on it. The distance from the left end of the bar to the i-th mark is Xi.

She will place several squares on this bar. Here, the following conditions must be met:

  • Only squares with integral length sides can be placed.
  • Each square must be placed so that its bottom side touches the bar.
  • The bar must be completely covered by squares. That is, no square may stick out of the bar, and no part of the bar may be left uncovered.
  • The boundary line of two squares may not be directly above a mark.

Examples of arrangements that satisfy/violate the conditions

The beauty of an arrangement of squares is defined as the product of the areas of all the squares placed. Joisino is interested in the sum of the beauty over all possible arrangements that satisfy the conditions. Write a program to find it. Since it can be extremely large, print the sum modulo 109+7.

Constraints

  • All input values are integers.
  • 1N109
  • 0M105
  • 1X1<X2<<XM1<XMN1

Input

Input is given from Standard Input in the following format:

N M
X1 X2  XM1 XM

Output

Print the sum of the beauty over all possible arrangements that satisfy the conditions, modulo 109+7.


Sample Input 1

Copy
3 1
2

Sample Output 1

Copy
13

There are two possible arrangements:

  • Place a square of side length 1 to the left, and place another square of side length 2 to the right
  • Place a square of side length 3

The sum of the beauty of these arrangements is (1×1×2×2)+(3×3)=13.


Sample Input 2

Copy
5 2
2 3

Sample Output 2

Copy
66

Sample Input 3

Copy
10 9
1 2 3 4 5 6 7 8 9

Sample Output 3

Copy
100

Sample Input 4

Copy
1000000000 0

Sample Output 4

Copy
693316425

题意:有N个格子,M个障碍(在格子边界上),你要在上面放若干个正方形,使得正方形的边界不经过障碍,每种方案的权值定义为所有正方形面积之积,求所有方案权值之和

题解:

我们可以构造一个新问题,使得对于一种方案a[1],a[2]...a[k](表示正方形边长),我们统计它∏a[i]^2次

然后可以理解为放隔板,两个隔板之间放一个红球和一个蓝球,问方案数

对于每一段无障碍的分别矩阵快速幂

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define fill( x, y ) memset( x, y, sizeof x )
#define copy( x, y ) memcpy( x, y, sizeof x )
using namespace std;

typedef long long LL;
typedef pair < int, int > pa;

const int mod = 1e9 + 7;

inline void inc(int &x, int y) { x += y; if( x >= mod ) x -= mod; }

struct Matrix
{
	int a[4][4];
	Matrix() { fill( a, 0 ); }
	inline void init() { for( int i = 0 ; i < 4 ; i++ ) a[ i ][ i ] = 1; }
	Matrix operator * ( const Matrix &b ) const
	{
		Matrix c;
		for( int k = 0 ; k < 4 ; k++ )
			for( int i = 0 ; i < 4 ; i++ )
				for( int j = 0 ; j < 4 ; j++ )
					inc( c.a[ i ][ j ], 1LL * a[ i ][ k ] * b.a[ k ][ j ] % mod );
		return c;
	}
}ans, p, q;

Matrix qpow(Matrix x, int y)
{
	Matrix ret; ret.init();
	for( ; y ; y >>= 1, x = x * x ) if( y & 1 ) ret = ret * x;
	return ret;
}

int lst, n, m;

int main()
{
#ifdef wxh010910
	freopen( "data.in", "r", stdin );
#endif
	scanf( "%d%d", &n, &m );
	ans.init();
	p.a[ 0 ][ 0 ] = 2; p.a[ 0 ][ 1 ] = 1; p.a[ 0 ][ 2 ] = 1; p.a[ 0 ][ 3 ] = 1;
	p.a[ 1 ][ 0 ] = 1; p.a[ 1 ][ 1 ] = 1; p.a[ 1 ][ 2 ] = 0; p.a[ 1 ][ 3 ] = 1;
	p.a[ 2 ][ 0 ] = 1; p.a[ 2 ][ 1 ] = 0; p.a[ 2 ][ 2 ] = 1; p.a[ 2 ][ 3 ] = 1;
	p.a[ 3 ][ 0 ] = 1; p.a[ 3 ][ 1 ] = 0; p.a[ 3 ][ 2 ] = 0; p.a[ 3 ][ 3 ] = 1;
	q.a[ 0 ][ 0 ] = 1; q.a[ 0 ][ 1 ] = 1; q.a[ 0 ][ 2 ] = 1; q.a[ 0 ][ 3 ] = 1;
	q.a[ 1 ][ 0 ] = 0; q.a[ 1 ][ 1 ] = 1; q.a[ 1 ][ 2 ] = 0; q.a[ 1 ][ 3 ] = 1;
	q.a[ 2 ][ 0 ] = 0; q.a[ 2 ][ 1 ] = 0; q.a[ 2 ][ 2 ] = 1; q.a[ 2 ][ 3 ] = 1;
	q.a[ 3 ][ 0 ] = 0; q.a[ 3 ][ 1 ] = 0; q.a[ 3 ][ 2 ] = 0; q.a[ 3 ][ 3 ] = 1;
	while( m-- )
	{
		int x;
		scanf( "%d", &x );
		ans = ans * qpow( p, ( x - lst - 1 ) ) * q;
		lst = x;
	}
	ans = ans * qpow( p, n - lst );
	printf( "%d\n", ans.a[ 0 ][ 3 ] );
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值