题目描述

众所周知,Alice和Bob非常喜欢博弈,而且Alice永远是先手,Bob永远是后手。

Alice和Bob面前有3堆石子,Alice和Bob每次轮流拿某堆石子中的若干个石子(不可以是0个),拿到所有石子中最后一个石子的人获胜。这是一个只有3堆石子的Nim游戏。

Bob错误的认为,三堆石子的Nim游戏只需要少的两堆的石子数量加起来等于多的那一堆,后手就一定会胜利。所以,Bob把三堆石子的数量分别设为 {k,4k,5k}(k>0)。

现在Alice想要知道,在k 小于 2^n 的时候,有多少种情况先手一定会获得胜利。

输入

一个整数n(1 \le n \le 2 \times 10^91≤n≤2×109)。

输出

输出先手胜利的可能情形数。答案对10^9+7109+7取模。

输出时每行末尾的多余空格,不影响答案正确性

样例输入

3

样例输出

2

题目来源

ACM训练联盟周赛

首先我们按照题目基本意思模拟打表可以得出

n  A胜  B胜

1   0      2

2   0      4

3   2      6

4   7      9

5   17    15

6   39    25

7   88    40

8   192  64

9   408  104

从上面的数据我们不难得到B获胜的可能性的规律是第五项开始,f(n)=f(n-1)+f(n-3)+f(n-4)

这样我们从第五项开始,就可以得到所有B获胜的可能数,而A获胜的可能数就是2^n-f(n)

题目给出的n的范围可以取到10^9,所以我们在求f(n)时要用到矩阵快速幂,求2^n时用快速幂

首先写出递推式的矩阵式

|  f(n-1)  f(n-2)  f(n-3)  f(n-4)  |         |   1  1  0  0  |

|     0         0         0         0     |    x    |  0  0  1  0  |

|     0         0         0         0     |         |   1  0  0  1  |

|     0         0         0         0     |         |   1  0  0  0  |

写出矩阵式后直接套用模板就可以求出f(n)

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define debug(a) cout << #a << " " << a << endl
using namespace std;
const int maxn = 1e4 + 10;
const int mod = 1e9 + 7;
typedef long long ll;
struct matrix {
ll a[10][10];
};
matrix base, ans;
matrix multiply( matrix x, matrix y ) {
matrix tmp;
for( ll i = 0; i < 4; i ++ ) {
for( ll j = 0; j < 4; j ++ ) {
tmp.a[i][j] = 0;
for( ll k = 0; k < 4; k ++ ) {
tmp.a[i][j] = ( tmp.a[i][j] + x.a[i][k]*y.a[k][j] ) % mod;
}
}
}
return tmp;
}
ll f( ll n ) {
while( n ) {
if( n&1 ) {
ans = multiply( ans, base );
}
base = multiply( base, base );
n /= 2;
}
return ans.a[0][0];
}
ll qow( ll a, ll b ) {
ll sum = 1;
while( b ) {
if( b&1 ) {
sum = sum*a%mod;
}
a = a*a%mod;
b /= 2;
}
return sum;
}
int main() {
ll n;
while( cin >> n ) {
memset( base.a, 0, sizeof(base.a) );
memset( ans.a, 0, sizeof(ans.a) );
ans.a[0][0] = 9, ans.a[0][1] = 6;
ans.a[0][2] = 4, ans.a[0][3] = 2;
base.a[0][0] = base.a[0][1] = base.a[1][2] =
base.a[2][0] = base.a[2][3] = base.a[3][0] = 1;
//debug(qow(2,n));
if( n == 1 || n == 2 ) {
cout << 0 << endl;
} else if( n == 3 ) {
cout << 2 << endl;
} else if( n == 4 ) {
cout << 7 << endl;
} else {
cout << ( qow(2,n) - f(n-4) + mod ) % mod << endl; //记得结果取模这里要先加mod再取模,否则会得到负值
}
}
return 0;
}

  

计蒜客 ACM训练联盟周赛 第一场 Alice和Bob的Nim游戏 矩阵快速幂的更多相关文章

  1. 计蒜客 ACM训练联盟周赛 第一场 Christina式方格取数 思维

    助手Christina发明了一种方格取数的新玩法:在n*m的方格棋盘里,每个格子里写一个数.两个人轮流给格子染色,直到所有格子都染了色.在所有格子染色完后,计算双方的分数.对于任意两个相邻(即有公共边 ...

  2. 计蒜客 ACM训练联盟周赛 第一场 从零开始的神棍之路 暴力dfs

    题目描述 ggwdwsbs最近被Zeratul和Kyurem拉入了日本麻将的坑.现在,ggwdwsbs有13张牌,Kyurem又打了一张,加起来有14张牌.ggwdwsbs想拜托你帮他判断一下,这14 ...

  3. ACM训练联盟周赛(第一场)

    B:Zeratul与Xor 题目描述 Xor(按位异或),对应C++中的“^”运算符. Zeratul给出了一个数列A[n](n≤105),要做q(q≤105)组动作,这些动作包括: 1  a:数列中 ...

  4. 计蒜客 28449.算个欧拉函数给大家助助兴-大数的因子个数 (HDU5649.DZY Loves Sorting) ( ACM训练联盟周赛 G)

    ACM训练联盟周赛 这一场有几个数据结构的题,但是自己太菜,不会树套树,带插入的区间第K小-替罪羊套函数式线段树, 先立个flag,BZOJ3065: 带插入区间K小值 计蒜客 Zeratul与Xor ...

  5. 2020牛客寒假算法基础集训营1 J. 缪斯的影响力 (矩阵快速幂/费马小定理降幂)

    https://ac.nowcoder.com/acm/problem/200658 f(n) = f(n-1) * f(n-2) * ab ,f的第一项是x,第二项是y. 试着推出第三项是x·y·a ...

  6. 2017ACM暑期多校联合训练 - Team 2 1006 HDU 6050 Funny Function (找规律 矩阵快速幂)

    题目链接 Problem Description Function Fx,ysatisfies: For given integers N and M,calculate Fm,1 modulo 1e ...

  7. 计蒜客 28437.Big brother said the calculation-线段树+二分-当前第k个位置的数 ( ACM训练联盟周赛 M)

    M. Big brother said the calculation 通过线段树维护. 这个题和杭电的一道题几乎就是一样的题目.HDU5649.DZY Loves Sorting 题意就是一个n的排 ...

  8. 计蒜客 ACM竞赛高校联盟训练赛 第8场 煎牛排

    水一水. https://nanti.jisuanke.com/t/24205 煎牛排 题目描述 又是一个难得的周六,是时候远离食堂和外卖出去大吃一顿了.圈内知名吃货AA正想着中午去吃汉堡炸鸡烤肉火锅 ...

  9. ACM训练联盟周赛 A. Teemo's bad day

    65536K   Today is a bad day. Teemo is scolded badly by his teacher because he didn't do his homework ...

随机推荐

  1. H3C模拟器实验之网络地址转换

    网络拓扑图 NOTE:各个设备的基本配置在拓扑图上已经标明(需要注意的是RTB的出接口也需要配置IP,但是使用ping -a 10.1.1.1 202.117.144.1 ping不通,这点不是很理解 ...

  2. 不用 Spring Security 可否?试试这个小而美的安全框架

    写在前面 在一款应用的整个生命周期,我们都会谈及该应用的数据安全问题.用户的合法性与数据的可见性是数据安全中非常重要的一部分.但是,一方面,不同的应用对于数据的合法性和可见性要求的维度与粒度都有所区别 ...

  3. MATLAB使用过程中遇到的问题(持续更新)

    note:如果对你有帮助,请点赞评论哟!!! 问题1:每次双击.m文件都会自动打开一个matlab程序 step1:下载这个文件 http://pan.baidu.com/s/1pL2ULOf ste ...

  4. 【Java例题】2.2 分数类

    2.定义分数类,包括分子和分母变量.构造方法. 加减乘除方法.化简方法.值计算方法和显示分子和分母的方法. 然后编写一个主类,在其主方法中通过定义两个分数对象来 显示每一个分数的分子值.分母值.化简和 ...

  5. Spark 系列(七)—— 基于 ZooKeeper 搭建 Spark 高可用集群

    一.集群规划 这里搭建一个 3 节点的 Spark 集群,其中三台主机上均部署 Worker 服务.同时为了保证高可用,除了在 hadoop001 上部署主 Master 服务外,还在 hadoop0 ...

  6. vue-cli项目下引入vant组件

    前言 Vant是有赞前端团队基于有赞统一的规范实现的 Vue 组件库,提供了一整套 UI 基础组件和业务组件.通过 Vant,可以快速搭建出风格统一的页面,提升开发效率.目前已有近50个组件,这些组件 ...

  7. Thread、ThreadPool、Task、Parallel、Async和Await基本用法、区别以及弊端

    多线程的操作在程序中也是比较常见的,比如开启一个线程执行一些比较耗时的操作(IO操作),而主线程继续执行当前操作,不会造成主线程阻塞.线程又分为前台线程和后台线程,区别是:整个程序必须要运行完前台线程 ...

  8. ABAP_增强点查找

    *&---------------------------------------------------------------------* *& Report Z_FIND_EN ...

  9. windbg 使用与技巧

    基本知识和常用命令 (1)       Windbg下载地址http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx 安装完后执行w ...

  10. ArrayList用法整理

    System.Collections.ArrayList类是一个特殊的数组.通过添加和删除元素,就可以动态改变数组的长度. 一.优点 1.支持自动改变大小的功能 2.可以灵活的插入元素 3.可以灵活的 ...