1411: [ZJOI2009]硬币游戏

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 897  Solved: 394
[Submit][Status][Discuss]

Description

Orez很喜欢玩游戏,他最近发明了一款硬币游戏。他在桌子的边缘上划分出2*n个位置并按顺时针把它们标号为1,2,……,2n,然后把n个硬币放在标号为奇数的位置上。接下来每次按如下操作:在任意两个硬币之间放上一个硬币,然后将原来的硬币拿走;所放硬币的正反面由它两边的两个硬币决定,若两个硬币均为正面朝上或反面朝上,则所放硬币为正面朝上,否则为反面朝上。
那么操作T次之后桌子边缘上硬币的情况会是怎样的呢?

Input

文件的第一行包含两个整数n和T。 接下的一行包含n个整数,表示最开始桌面边缘的硬币摆放情况,第i个整数ai表示第i个硬币摆放在2*i-1个位置上,ai=1表示正面朝上,ai=2表示反面朝上。

Output

文件仅包含一行,为2n个整数,其中第i个整数bi桌面边缘的第i个位置上硬币的情况,bi=1表示正面朝上,bi=2表示反面朝上,bi=0表示没有硬币。

Sample Input

10 5
2 2 2 1 1 1 1 1 1 2

Sample Output

0 1 0 1 0 1 0 1 0 2 0 1 0 2 0 1 0 1 0 1

数据范围
30%的数据 n≤1000 T≤1000
100%的数据 n≤100000 T≤2^60

HINT

Source

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1411或者https://vijos.org/p/1554

题目大意:给定一圈硬币,T次操作,每次操作在每个硬币中间各放一枚硬币,硬币的正反面由它旁边两个决定,两边相同则为正面,两边不相同则为反面,然后将之前的硬币全部撤掉,问T次操作后的硬币序列,T<=2^60

首先我们令硬币正面为0 反面为1 那么很容易发现新硬币的值为两边硬币的异或值 样例也就很好解释了

1-1-1-0-0-0-0-0-0-1-   0
-0-0-1-0-0-0-0-0-1-0   1
0-0-1-1-0-0-0-0-1-1-   2
-0-1-0-1-0-0-0-1-0-1   3
1-1-1-1-1-0-0-1-1-1-   4
-0-0-0-0-1-0-1-0-0-0   5

然后这题n<=10W 矩阵乘法一定MLE 即使矩阵特殊构造可以干掉一维空间复杂度 O(n^2*logT)的时间也无法承受

我们只考虑偶数的行

易知第二行每个数是原序列该位置左右两个数的异或

由数学归纳法可以 第2^k行每个数是原序列该位置左侧第2^(k-1)个数和右侧第2^(k-1)个数的异或

然后将T进行二进制拆分,每位进行一次变换即可 最后再讨论T的奇偶

时间复杂度O(n*logT)

膜拜出题人,膜拜题解人,这TM也成,我服了!

下面给出AC代码:

 #include <bits/stdc++.h>
#define in freopen("coin.in","r",stdin);
#define out freopen("coin.out","w",stdout);
#define M 100100
using namespace std;
typedef long long ll;
ll n,T,tot;
char a[][M],ans[M<<];
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
int main()
{
ll i,j,x;
n=read();
T=read();
for(i=;i<=n;i++)
{
x=read();
a[][i]=x-;
}
for(j=;j<=T;j<<=)
{
if(T&j)
{
tot++;
for(i=;i<=n;i++)
{
ll x1=(i+(j>>)%n+n-)%n+;
ll y1=(i-(j>>)%n+n-)%n+;
a[tot&][i]=a[~tot&][x1]^a[~tot&][y1];
}
}
}
for(i=;i<=n;i++)
{
ans[i+i-]=a[tot&][i];
}
if(T&)
{
for(i=;i<=n;i++)
{
ans[i<<]=ans[i+i-]^ans[i==n?:i<<|];
}
for(i=;i<=n;i++)
{
ans[i+i-]=-;
}
}
else
{
for(i=;i<=n;i++)
{
ans[i+i]=-;
}
}
for(i=;i<=n<<;i++)
{
printf("%d%c",ans[i]+,i==n+n?'\n':' ');
}
return ;
}

以上方法我还是有点迷,下面换种写法,

对于样例,进行数学归纳,发现2^k变换之后,第i个位置的硬币情况只与它左右的第k+1个硬币有关。

如k=0,第3位硬币情况只与2和4位硬币有关。因为t可以拆成若干个2^k的和,于是对每个2^k进行O(n)的变换,总复杂度O(nlogt)。

 #include <bits/stdc++.h>
#define in freopen("coin.in","r",stdin);
#define out freopen("coin.out","w",stdout);
typedef long long ll;
using namespace std;
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
const int N=;
ll n,t,a[N],b[N];
ll f(ll b,ll k)
{
ll x=b-k;
ll y=b+k;
x=(x%(n<<)+(n<<)-)%(n<<)+;
y=(y-)%(n<<)+;
if(k==)
return a[x];
if(a[x]==)
return ;
if(a[x]==a[y])
return ;
else return ;
}
void work(ll k,ll q)
{
if(k==)
return;
work(k>>,q<<);
if(k%==)
{
memset(b,false,sizeof(b));
for(ll j=;j<=(n<<);j++)
b[j]=f(j,q);
swap(a,b);
}
}
int main()
{
n=read();
t=read();
for(ll i=;i<=n;i++)
a[(i<<)-]=read();
work(t,);
for(ll i=;i<(n<<);i++)
cout<<a[i]<<" ";
cout<<a[n<<]<<endl;
return ;
}

BZOJ 1411&&Vijos 1544 : [ZJOI2009]硬币游戏【递推,快速幂】的更多相关文章

  1. bzoj1411: [ZJOI2009]硬币游戏

    1411: [ZJOI2009]硬币游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 965  Solved: 420[Submit][Status ...

  2. 【BZOJ】2017: [Usaco2009 Nov]硬币游戏(dp+神题+博弈论)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2017 这题太神了,我想了一个中午啊 原来是看错题一直没理解题解说的,一直以为题解是错的QAQ “开始 ...

  3. [ZJOI2009]硬币游戏

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 920  Solved: 406[Submit][Status][Discuss] Descriptio ...

  4. 【BZOJ】1088: [SCOI2005]扫雷Mine(递推)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1088 脑残去想递推去了... 对于每一个第二列的格子,考虑多种情况,然后转移.....QAQ 空间可 ...

  5. bzoj1042硬币购物——递推+容斥

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1042 递推,再用容斥原理减掉多余的,加上多减的……(dfs)即可. 代码如下: #includ ...

  6. CH3401 石头游戏(矩阵快速幂加速递推)

    题目链接:传送门 题目: 石头游戏 0x30「数学知识」例题 描述 石头游戏在一个 n 行 m 列 (≤n,m≤) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这10个数 ...

  7. bzoj 1089 SCOI2003严格n元树 递推

    挺好想的,就是一直没调过,我也不知道哪儿的错,对拍也拍了,因为数据范围小,都快手动对拍了也不知道 哪儿错了.... 我们定义w[i]代表深度<=i的严格n元树的个数 那么最后w[d]-w[d-1 ...

  8. TZOJ 5291 游戏之合成(快速幂快速乘)

    描述 zzx和city在玩一款小游戏的时候,游戏中有一个宝石合成的功能,需要m个宝石才可以合成下一级的宝石(例如需要m个1级宝石才能合成2级宝石). 这时候zzx问city说“我要合成A级宝石需要多少 ...

  9. P5110 块速递推-光速幂、斐波那契数列通项

    P5110 块速递推 题意 多次询问,求数列 \[a_i=\begin{cases}233a_{i-1}+666a_{i-2} & i>1\\ 0 & i=0\\ 1 & ...

随机推荐

  1. HTTP之URL分解

    HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接.URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息 URL,全称是U ...

  2. iOS 本地项目上传github,github管理项目配置

    一.注册github账号   首先需要注册一个github账号,注册地址:https://github.com 接着会来到这 然后会收到一封github发的邮件,进入邮箱验证 二.创建个人的githu ...

  3. npm的使用总结

    npm常用命令 npm list 查看当前目录下已安装的包 npm root -g 查看全局安装的包的路径 npm help 查看全部命令 npm update/uninstall moduleNam ...

  4. [WinForm]委托应用①——窗口之间方法/控件调用

    不传参数 第二窗口:public partial class Form2 : Form { /// <summary> /// 定义委托 /// </summary> publ ...

  5. Java I/O---输入与输出

    编程语言的I/O类库中常使用流这个抽象概念, 它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象. "流" 屏蔽了实际的I/O设备中处理数据的细节.Java类库中 ...

  6. python方法的延迟加载

    数据挖掘的过程中,数据进行处理是一重要的环节,我们往往会将其封装成一个方法,而有的时候这一个方法可能会被反复调用,每一次都对数据进行处理这将是一个很耗时耗资源的操纵,那么有没有办法将计算后的结果缓存起 ...

  7. 虚拟机下linux系统安装nginx

    近在windows虚机下安装nginx,也遇到部分问题,写篇随笔总结一下 一.安装虚机 windows下安装虚拟机我就不说了,一搜一大把,一直下一步就ok了 二. 打开虚拟安装nginx 1.选择版本 ...

  8. 微信小程序参数二维码6问6答

    微信小程序参数二维码[基础知识篇],从6个常见问题了解小程序参数二维码的入门知识. 1.什么是小程序参数码? 微信小程序参数二维码:针对小程序特定页面,设定相应参数值,用户扫描后进入相应的页面. 2. ...

  9. Effective Java 第三版——16.在公共类中使用访问方法而不是公共属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  10. js介绍

    ---恢复内容开始--- js介绍 最近学习了js,那么我今天给大家介绍下js.希望对初学者有些帮助. js就是常说的JavaScript.JavaScript是目前世界上最流行的编程语言之一.这门语 ...