B. Ralph And His Magic Field(思维-奶牛翻块)

https://codeforces.com/problemset/problem/894/B


题目描述

Ralph has a magic field which is divided into n×mn×m blocks. That is to say, there are nn rows and mm 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 kk , where kk 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=10^{9}+71000000007=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.

输入格式

The only line contains three integers nn , mm and kk ( 1<=n,m<=10^{18}1<=n,m<=1018 , kk is either 1 or -1).

输出格式

Print a single number denoting the answer modulo 10000000071000000007 .

题意翻译

一个n*m的方格网,要在每个方格里都填上一个整数并且使得每一行每一列填的数的乘积都为k,输出填数的方案的总数模1e9+7.保证k=1或者-1.

感谢@Fuko_Ibuki 提供的翻译

输入输出样例

输入 #1复制

1 1 -1

输出 #1复制

1

输入 #2复制

1 3 1

输出 #2复制

1

输入 #3复制

3 3 -1

输出 #3复制

16

说明/提示

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.


思路:刚看的时候还想着讨论一下,看了看数据范围,猜测是个2的次幂的结论。

具体怎么想呢?确实开始容易陷进去构造,但是很明显这样去构造是很难的。当我知道了一个块的最后一行的一个时候,那么这个块对应的一整列的最终状态就确定了。比如我要最终是-1,那么我要是一列的最后一个是1,那么这一列上面的整个状态合起来就是-1。或者这一列最后一个是-1,上面整个状态是1。

也就是说,不管上面的最终状态是如何的,我最后一个都能根据结果使得这一列成功满足。同理这样一列列推过去到m-1列,开始同理推1,....n-1行。

那么(n-1)*(m-1)的范围内可以随意搞多少个呢?2^[(n-1)*(m-1)]

那么(n,m)能否使对应的行列合法呢?当n+m为奇数的时候,-1时候是不合法的。n/m有一个是奇数,假设n为奇数,那么对应的-1总数要是奇数个,而m为偶数,对应的-1个数是偶数个,不成立。

代码上注意:以后如果ksm里面乘数过大,把ksm分开去乘。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5;
typedef long long LL;
const LL mod=1000000007;
inline LL ksm(LL x,LL a){
	LL ret=1,k=x;
	for (;a;a>>=1,k=k*k%mod)
		if (a&1) ret=ret*k%mod;
	return ret%mod;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n,m,k;cin>>n>>m>>k;
  if( (n+m)&1&&k==-1) cout<<0<<endl;
  else{
  	LL ans=ksm(2,n-1);
  	cout<<ksm(ans,m-1)<<endl;
  	//cout<<ksm(2,(n-1)*(m-1))<<endl;
  }
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108522236