Codeforces Round #277.5(Div. 2) F. Special Matrices【思维+Dp】好题~好题~
2017-04-20 17:24
483 查看
F. Special Matrices
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
An n × n square matrix is
special, if:
it is binary, that is, each cell contains either a 0, or a 1;
the number of ones in each row and column equals 2.
You are given n and the first
m rows of the matrix. Print the number of special
n × n matrices, such that the first
m rows coincide with the given ones.
As the required value can be rather large, print the remainder after dividing the value by the given number
mod.
Input
The first line of the input contains three integers n,
m, mod (2 ≤ n ≤ 500,
0 ≤ m ≤ n,
2 ≤ mod ≤ 109). Then
m lines follow, each of them contains n characters — the first rows of the required special matrices. Each of these lines contains exactly two characters '1', the
rest characters are '0'. Each column of the given
m × n table contains at most two numbers one.
Output
Print the remainder after dividing the required value by number
mod.
Examples
Input
Output
Input
Output
Note
For the first test the required matrices are:
In the second test the required matrix is already fully given, so the answer is 1.
题目大意:
让你构造出来一个N*N的矩阵,使得每行每列保证只有两个1。
现在已经给出M行的矩阵部分,问最终可以得到多少个可行方案。
思路(思路源自:http://blog.csdn.net/u014733623/article/details/41250593):
1、一开始想的是设定dp【i】【x】【y】【2(k)】【2(l)】表示到第i列 ,这一列的放置1的两个位子在x,y上,对应这两行上边出现1的个数为k,l个的方案数。
状态转移方程很好写,但是时间复杂度不允许,会达到O(n^5*4);
再之后就不会设定了。
其实反向想一下,考虑剩余部分就好了。
2、设定dp【s1】【s2】表示到第i行,剩余s1个列可以放置两个1,剩余s2个列可以放置1个1的方案数。
那么就有:
dp【s1-2】【s2】=dp【s1】【s2】*C(s1,2);
dp【s1-1】【s2】=dp【s1】【s2】*C(s1,1)*C(s2,1);
dp【s1】【s2-2】=dp【s1】【s2】*C(s2,2);
我们可以枚举行和s1,s2=(n-i+1)*2-s1*2【剩余需要放置1的个数-s1*2==剩余需要放置1的个数==s2】;
时间复杂度O(n^2);
解法真的很巧妙。点个赞。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
#define ll __int64
char a[505][505];
ll dp[606][606];
ll num[606];
int main()
{
ll n,m,mod;
while(~scanf("%I64d%I64d%I64d",&n,&m,&mod))
{
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
for(ll i=1;i<=m;i++)scanf("%s",a[i]+1);
ll s1=0;
ll s2=0;
for(ll i=1;i<=m;i++)
{
for(ll j=1;j<=n;j++)
{
if(a[i][j]=='1')num[j]++;
}
}
for(ll j=1;j<=n;j++)
{
if(num[j]==0)s1++;
if(num[j]==1)s2++;
}
dp[s1][s2]=1;
for(ll i=m+1;i<=n;i++)
{
for(ll s1=0;s1<=n;s1++)
{
ll s2=(n-i+1)*2-s1*2;
if(s2<0||s2>n)continue;
if(s1-2>=0)dp[s1-2][s2+2]+=(dp[s1][s2]*(s1)*(s1-1)/2)%mod;
if(s1-1>=0)dp[s1-1][s2]+=(dp[s1][s2]*(s1)*(s2))%mod;
if(s2-2>=0)dp[s1][s2-2]+=(dp[s1][s2]*(s2)*(s2-1)/2)%mod;
}
}
printf("%I64d\n",dp[0][0]);
}
}
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
An n × n square matrix is
special, if:
it is binary, that is, each cell contains either a 0, or a 1;
the number of ones in each row and column equals 2.
You are given n and the first
m rows of the matrix. Print the number of special
n × n matrices, such that the first
m rows coincide with the given ones.
As the required value can be rather large, print the remainder after dividing the value by the given number
mod.
Input
The first line of the input contains three integers n,
m, mod (2 ≤ n ≤ 500,
0 ≤ m ≤ n,
2 ≤ mod ≤ 109). Then
m lines follow, each of them contains n characters — the first rows of the required special matrices. Each of these lines contains exactly two characters '1', the
rest characters are '0'. Each column of the given
m × n table contains at most two numbers one.
Output
Print the remainder after dividing the required value by number
mod.
Examples
Input
3 1 1000 011
Output
2
Input
4 4 100500 0110 1010 0101 1001
Output
1
Note
For the first test the required matrices are:
011101110
011110
101
In the second test the required matrix is already fully given, so the answer is 1.
题目大意:
让你构造出来一个N*N的矩阵,使得每行每列保证只有两个1。
现在已经给出M行的矩阵部分,问最终可以得到多少个可行方案。
思路(思路源自:http://blog.csdn.net/u014733623/article/details/41250593):
1、一开始想的是设定dp【i】【x】【y】【2(k)】【2(l)】表示到第i列 ,这一列的放置1的两个位子在x,y上,对应这两行上边出现1的个数为k,l个的方案数。
状态转移方程很好写,但是时间复杂度不允许,会达到O(n^5*4);
再之后就不会设定了。
其实反向想一下,考虑剩余部分就好了。
2、设定dp【s1】【s2】表示到第i行,剩余s1个列可以放置两个1,剩余s2个列可以放置1个1的方案数。
那么就有:
dp【s1-2】【s2】=dp【s1】【s2】*C(s1,2);
dp【s1-1】【s2】=dp【s1】【s2】*C(s1,1)*C(s2,1);
dp【s1】【s2-2】=dp【s1】【s2】*C(s2,2);
我们可以枚举行和s1,s2=(n-i+1)*2-s1*2【剩余需要放置1的个数-s1*2==剩余需要放置1的个数==s2】;
时间复杂度O(n^2);
解法真的很巧妙。点个赞。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
#define ll __int64
char a[505][505];
ll dp[606][606];
ll num[606];
int main()
{
ll n,m,mod;
while(~scanf("%I64d%I64d%I64d",&n,&m,&mod))
{
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
for(ll i=1;i<=m;i++)scanf("%s",a[i]+1);
ll s1=0;
ll s2=0;
for(ll i=1;i<=m;i++)
{
for(ll j=1;j<=n;j++)
{
if(a[i][j]=='1')num[j]++;
}
}
for(ll j=1;j<=n;j++)
{
if(num[j]==0)s1++;
if(num[j]==1)s2++;
}
dp[s1][s2]=1;
for(ll i=m+1;i<=n;i++)
{
for(ll s1=0;s1<=n;s1++)
{
ll s2=(n-i+1)*2-s1*2;
if(s2<0||s2>n)continue;
if(s1-2>=0)dp[s1-2][s2+2]+=(dp[s1][s2]*(s1)*(s1-1)/2)%mod;
if(s1-1>=0)dp[s1-1][s2]+=(dp[s1][s2]*(s1)*(s2))%mod;
if(s2-2>=0)dp[s1][s2-2]+=(dp[s1][s2]*(s2)*(s2-1)/2)%mod;
}
}
printf("%I64d\n",dp[0][0]);
}
}
相关文章推荐
- Codeforces Round #277.5 (Div. 2)-F. Special Matrices
- Codeforces Round #277.5 (Div. 2) F. Special Matrices
- Codeforces Round #277.5 (Div. 2) E. Hiking(二分 DP)
- Codeforces Round #426 (Div. 2) C. The Meaningless Game 思维 D. The Bakery dp
- 【Codeforces Round 336 (Div 2) C】【贪心 DP思维】Chain Reaction 每个灯塔位置为a[]破坏b[]范围所有灯塔 设置一个灯塔使得最多灯塔被保留
- Codeforces Round #387(Div. 2)D. Winter Is Coming【思维+dp】
- Codeforces Round #277.5 (Div. 2)
- Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo DP+矩阵快速幂加速
- Codeforces Round #Pi (Div. 2) F. Mausoleum DP
- Codeforces Round #282 Div.1 B Obsessive String --DP
- Codeforces Round #367 (Div. 2) C. Hard problem (dp)
- Codeforces Round #381 (Div. 2)C(构造,思维)
- Codeforces Round #419 (Div. 2) E. Karen and Supermarket(树形DP)
- Codeforces Round #272 (Div. 2) D. Dreamoon and Sets (思维 数学 规律)
- Codeforces Round #468 (Div. 2): F. Teodor is not a liar!(DP)
- 【Codeforces Round 263 (Div 2)D】【树形DP】Appleman and Tree 树上割k个黑点为k块的方案数
- Codeforces Round #363 (Div. 2) C. Vacations(DP 动态规划)
- Codeforces Round #139 (Div. 2)C Barcode DP
- Codeforces Round #202 (Div. 1) (树形dp, dp)
- Codeforces Round #400 (Div. 1 + Div. 2, combined)C. Molly's Chemicals【思维】