CodeForces - 894B Ralph And His Magic Field(给出n*m的格子 和 k为1或-1,往里填1 或 -1,使得每一行和每一列都和k相等)

Ralph has a magic field which is divided into n × m blocks. That is to say, there are n rows and m columns on the field. Ralph can put an integer in each block. However, the magic field doesn't always work properly. It works only if the product of integers in each row and each column equals to k, where k is either 1 or -1.

Now Ralph wants you to figure out the number of ways to put numbers in each block in such a way that the magic field works properly. Two ways are considered different if and only if there exists at least one block where the numbers in the first way and in the second way are different. You are asked to output the answer modulo 1000000007 = 109 + 7.

Note that there is no range of the numbers to put in the blocks, but we can prove that the answer is not infinity.

Input

The only line contains three integers nm and k (1 ≤ n, m ≤ 1018k is either 1 or -1).

Output

Print a single number denoting the answer modulo 1000000007.

Example
Input
1 1 -1
Output
1
Input
1 3 1
Output
1
Input
3 3 -1
Output
16
Note

In the first example the only way is to put -1 into the only block.

In the second example the only way is to put 1 into every block.


题意: 给出n*m的格子,和一个数 k,让往n*m的盒子里填1,或-1,使得每一行和每一列的乘积都和k相等,看看有多少种方法;

思路:

    你可以这样想,先看一行(或一列),不管这些格子前面怎么填,这一行(或这一列)的乘积的控制权,都在最后一个格子上,若 k==1  前面的格子乘积为1,最后一个格子填1,前面的格子乘积为-1,最后一个格子就填-1; 按着思路想,若给出你 n*m 个格子,你把第n行和第m列的格子空出来(为了满足每一行或每一列都等于k),不管前面(n-1)*(m-1)个格子怎么填,都会被第n行和第m列的格子所控制这一列和这一行乘积;

有人会问那么的n行的乘积和第m的乘积都等于k啊,其实你根本就不用控制,你为了控制n-1行和m-1列的乘积都等于k,你除了n*m那个位置格子没有填,第n行和第m列的其他位置都填满了,这时候为了使第n行和第m列的乘积都等于k,n*m位置的格子填什么都已经确定了;

因为每一个格子都有对应的行和对应的列,这个填啥,即影响这一行的乘积,也影响这一列的乘积;

共有的方法:2^((n-1)*(m-1)) 种; n和m都太大,所以可以按这样的顺序求(2^(n-1))^(m-1)

但要注意当k==-1时, n+m 为奇数时,是凑不成的; 

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
ll Mod_pow(ll x,ll n)
{
	ll res = 1;
	while(n>0)
	{
		if(n&1)
		  res = (res * x) % mod;
		x = x * x % mod;
		n>>=1;		
	}
	return res; 
}
int main()
{
	ll i,j,n,m,k;
	while(~scanf("%lld%lld%lld",&n,&m,&k))
	{
		if((n+m)%2&&k==-1)
			printf("0\n");
		else
			printf("%lld\n",Mod_pow(Mod_pow(2,n-1),m-1));
	}
	return 0;
} 




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值