计蒜客 ACM训练联盟周赛 第一场 Alice和Bob的Nim游戏 矩阵快速幂
题目描述
众所周知,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
题目来源
首先我们按照题目基本意思模拟打表可以得出
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游戏 矩阵快速幂的更多相关文章
- 计蒜客 ACM训练联盟周赛 第一场 Christina式方格取数 思维
助手Christina发明了一种方格取数的新玩法:在n*m的方格棋盘里,每个格子里写一个数.两个人轮流给格子染色,直到所有格子都染了色.在所有格子染色完后,计算双方的分数.对于任意两个相邻(即有公共边 ...
- 计蒜客 ACM训练联盟周赛 第一场 从零开始的神棍之路 暴力dfs
题目描述 ggwdwsbs最近被Zeratul和Kyurem拉入了日本麻将的坑.现在,ggwdwsbs有13张牌,Kyurem又打了一张,加起来有14张牌.ggwdwsbs想拜托你帮他判断一下,这14 ...
- ACM训练联盟周赛(第一场)
B:Zeratul与Xor 题目描述 Xor(按位异或),对应C++中的“^”运算符. Zeratul给出了一个数列A[n](n≤105),要做q(q≤105)组动作,这些动作包括: 1 a:数列中 ...
- 计蒜客 28449.算个欧拉函数给大家助助兴-大数的因子个数 (HDU5649.DZY Loves Sorting) ( ACM训练联盟周赛 G)
ACM训练联盟周赛 这一场有几个数据结构的题,但是自己太菜,不会树套树,带插入的区间第K小-替罪羊套函数式线段树, 先立个flag,BZOJ3065: 带插入区间K小值 计蒜客 Zeratul与Xor ...
- 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 ...
- 2017ACM暑期多校联合训练 - Team 2 1006 HDU 6050 Funny Function (找规律 矩阵快速幂)
题目链接 Problem Description Function Fx,ysatisfies: For given integers N and M,calculate Fm,1 modulo 1e ...
- 计蒜客 28437.Big brother said the calculation-线段树+二分-当前第k个位置的数 ( ACM训练联盟周赛 M)
M. Big brother said the calculation 通过线段树维护. 这个题和杭电的一道题几乎就是一样的题目.HDU5649.DZY Loves Sorting 题意就是一个n的排 ...
- 计蒜客 ACM竞赛高校联盟训练赛 第8场 煎牛排
水一水. https://nanti.jisuanke.com/t/24205 煎牛排 题目描述 又是一个难得的周六,是时候远离食堂和外卖出去大吃一顿了.圈内知名吃货AA正想着中午去吃汉堡炸鸡烤肉火锅 ...
- 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 ...
随机推荐
- openGL基本概念
OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行.OpenGL的状态通常被称为OpenGL上下文(Context).我们通常使用如下途径去 ...
- iDevice取证的一大突破
近日手机取证领域传出令人震撼的消息,知名取证大厂Cellebrite宣称可破解任何版本,任何机型的iDevice,连最新的iPhone X也逃不过. 若真属实,代表着iOS的取证又重现光明.只是不确定 ...
- 夯实Java基础(四)——面向对象之多态
1.多态介绍 面向对象三大特征:封装.继承.多态.多态是Java面向对象最核心,最难以理解的内容.从一定角度来看,封装和继承几乎都是为多态而准备的. 多态就是指程序中定义的引用变量所指向的具体类型和通 ...
- Qt实现表格树控件-自绘树节点虚线
目录 一.开心一刻 二.自绘树节点? 三.效果展示 四.实现思路 1.可扩展接口 2.函数重写 3.同步左侧表头 五.相关文章 原文链接:Qt实现表格树控件-自绘树节点虚线 一.开心一刻 一程序员第一 ...
- Linux故障处理最佳实践
引言 业务中断了! 老板咆哮,主管抓狂,而你就是那个要去处理故障.恢复业务的不幸的人. 你独自一人在阴暗的隔间里.北边是老板的办公室,西边是Team Leader的办公室,南面是茶水间,在那你能泡上一 ...
- Java并发编程实战笔记—— 并发编程2
1.ThreadLocal Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作.因此,尽管有两个线程同时执行一段相同的代码,而且这段代码又有一个指向同一个ThreadL ...
- 带你剖析WebGis的世界奥秘----Geojson数据加载(高级)
前言:前两周我带你们分析了WebGis中关键步骤瓦片加载+点击事件(具体的看前两篇文章),下面呢,我带大家来看看Geojson的加载及其点击事件 Geojson数据解析 GeoJSON是一种对各种地理 ...
- soap天气查询
public class MainActivity extends AppCompatActivity { private TextView tvContent; @Override protecte ...
- 发布一个自己的jar包给全球人使用
目录 项目准备 sonatype 注册 申请sonatype工单 gpg配置 项目配置 依赖oss-parent 自定义配置 pom配置 全局settings配置 发布 验证 maven 项目对于我们 ...
- c# 三步递交模式调用同一个存储过程
主要用于批量的sql操作:第一步创建中间表,第二步多次写数据到中间表,第三步 提交执行 创建三步递交的存储过程: CREATE PROC usp_testsbdj@bz int=0,@name VAR ...