CF894B Ralph And His Magic Field

题目链接:http://codeforces.com/contest/894/problem/B

题目大意:

  往一个 \(n \times m\) 的网格中填数字 \((1 \le n,m \le 10^{18})\),使得网格的任意一行和任意一列的乘积均为 \(k (k \in \{-1, 1\}).\)问有多少种方案。

知识点:  费马小定理、快速幂

解题思路:

  1、网格中的数字,要么是 1,要么是 -1;

  2、如果网格中 \((n-1) \times (m-1)\) 的子网格上的数字已经确定,那么最后一行和最后一列上的数字也随之确定,整个网格亦即随之确定,因此填数字的方案数为 \(2^{(n-1)(m-1)}\). 要理解这个结论为什么成立,可以试着想象:当网格中 \((n-1) \times (m-1)\) 的子网格上填满 1(此时最后一行和最后一列也已经确定),如果改变子网格上的数字,只要随之改变外层的数字即可。但是,在一种情况下答案为 0 :当 \(k = -1\) 并且 n 和 m 的奇偶性不同时。对于这一点,我们可以这么分析:

  假设 \(k = -1, n = 1, m = 2x (x \in N)\),答案显然为 0;

  则 \(k = -1, n = 2, m = 2x + 1 (x \in N)\),答案为 0;

  由此类推,\(k = -1, n = 1 + y, m = 2x + y (x, y \in N)\),答案亦为 0.

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 typedef long long ll;
 6 const ll mod = 1000000007;
 7 
 8 ll Fast_Power(ll t){//快速幂
 9     ll ret=1;
10     ll a=2;
11     while(t){
12         if(t&1) ret=ret*a%mod;
13         t>>=1;
14         a=a*a%mod;
15     }
16     return ret;
17 }
18 int main()
19 {
20     ll n,m;
21     int k;
22     scanf("%lld%lld%d",&n,&m,&k);
23     if(k==-1&&(n%2!=m%2))
24         printf("0\n");
25     else{
26         ll ans=Fast_Power(((n-1)%(mod-1))*((m-1)%(mod-1))%(mod-1))%mod;//此处应用费马小定理
27         printf("%lld\n",ans);
28     }
29     return 0;
30 }

 

posted @ 2017-11-27 21:31  Blogggggg  阅读(219)  评论(0编辑  收藏  举报