BZOJ 1411Vijos 1544 : [ZJOI2009]硬币游戏【递推,快速幂】
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
2 2 2 1 1 1 1 1 1 2
Sample Output
数据范围
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代码:
1 #include <bits/stdc++.h> 2 #define in freopen("coin.in","r",stdin); 3 #define out freopen("coin.out","w",stdout); 4 #define M 100100 5 using namespace std; 6 typedef long long ll; 7 ll n,T,tot; 8 char a[2][M],ans[M<<1]; 9 inline ll read() 10 { 11 ll x=0,f=1; 12 char ch=getchar(); 13 while(ch<'0'||ch>'9') 14 { 15 if(ch=='-') 16 f=-1; 17 ch=getchar(); 18 } 19 while(ch>='0'&&ch<='9') 20 { 21 x=x*10+ch-'0'; 22 ch=getchar(); 23 } 24 return x*f; 25 } 26 int main() 27 { 28 ll i,j,x; 29 n=read(); 30 T=read(); 31 for(i=1;i<=n;i++) 32 { 33 x=read(); 34 a[0][i]=x-1; 35 } 36 for(j=2;j<=T;j<<=1) 37 { 38 if(T&j) 39 { 40 tot++; 41 for(i=1;i<=n;i++) 42 { 43 ll x1=(i+(j>>1)%n+n-1)%n+1; 44 ll y1=(i-(j>>1)%n+n-1)%n+1; 45 a[tot&1][i]=a[~tot&1][x1]^a[~tot&1][y1]; 46 } 47 } 48 } 49 for(i=1;i<=n;i++) 50 { 51 ans[i+i-1]=a[tot&1][i]; 52 } 53 if(T&1) 54 { 55 for(i=1;i<=n;i++) 56 { 57 ans[i<<1]=ans[i+i-1]^ans[i==n?1:i<<1|1]; 58 } 59 for(i=1;i<=n;i++) 60 { 61 ans[i+i-1]=-1; 62 } 63 } 64 else 65 { 66 for(i=1;i<=n;i++) 67 { 68 ans[i+i]=-1; 69 } 70 } 71 for(i=1;i<=n<<1;i++) 72 { 73 printf("%d%c",ans[i]+1,i==n+n?'\n':' '); 74 } 75 return 0; 76 }
以上方法我还是有点迷,下面换种写法,
对于样例,进行数学归纳,发现2^k变换之后,第i个位置的硬币情况只与它左右的第k+1个硬币有关。
如k=0,第3位硬币情况只与2和4位硬币有关。因为t可以拆成若干个2^k的和,于是对每个2^k进行O(n)的变换,总复杂度O(nlogt)。
1 #include <bits/stdc++.h> 2 #define in freopen("coin.in","r",stdin); 3 #define out freopen("coin.out","w",stdout); 4 typedef long long ll; 5 using namespace std; 6 inline ll read() 7 { 8 ll x=0,f=1; 9 char ch=getchar(); 10 while(ch<'0'||ch>'9') 11 { 12 if(ch=='-') 13 f=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') 17 { 18 x=x*10+ch-'0'; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 const int N=200020; 24 ll n,t,a[N],b[N]; 25 ll f(ll b,ll k) 26 { 27 ll x=b-k; 28 ll y=b+k; 29 x=(x%(n<<1)+(n<<1)-1)%(n<<1)+1; 30 y=(y-1)%(n<<1)+1; 31 if(k==0) 32 return a[x]; 33 if(a[x]==0) 34 return 0; 35 if(a[x]==a[y]) 36 return 1; 37 else return 2; 38 } 39 void work(ll k,ll q) 40 { 41 if(k==0) 42 return; 43 work(k>>1,q<<1); 44 if(k%2==1) 45 { 46 memset(b,false,sizeof(b)); 47 for(ll j=1;j<=(n<<1);j++) 48 b[j]=f(j,q); 49 swap(a,b); 50 } 51 } 52 int main() 53 { 54 n=read(); 55 t=read(); 56 for(ll i=1;i<=n;i++) 57 a[(i<<1)-1]=read(); 58 work(t,1); 59 for(ll i=1;i<(n<<1);i++) 60 cout<<a[i]<<" "; 61 cout<<a[n<<1]<<endl; 62 return 0; 63 }
转载于:https://www.cnblogs.com/ECJTUACM-873284962/p/7102510.html
BZOJ 1411Vijos 1544 : [ZJOI2009]硬币游戏【递推,快速幂】相关推荐
- Japanese Student Championship 2021 D - Nowhere P(递推 + 快速幂)
传送门 这题很明显存在一个递推关系,思考了一下果然如此. 设dp[i][j]为前i项的和膜p为j的方案数,显然dp[i+1][j] = sum(dp[i][k]), (k + j != p), 那么问 ...
- Bzoj 1046: [HAOI2007]上升序列 二分,递推
1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3671 Solved: 1255 [Submit][St ...
- 【bzoj 4451】[Cerc2015]Frightful Formula - 递推
才没有在做cerc2015呢 看到好像不少人这题写fft卡得死死的啊,不如 O(n) O(n) 递推(雾) 首先可以观察出 (i,1) (i,1)这个格子为 x x时对(n,n)(n,n) a,b a ...
- 【noip2016十连测round3】T3 涂色游戏 【矩阵快速幂优化dp】
涂色游戏 题解: 推一推公式. 我们让f[i][j]表示第i列有j种颜色的方案总数,k表示i-1列用了多少种颜色,l表示第i列用了多少种没有在i-1列出现的颜色,G(i,j)表示i个格子涂j种颜色的方 ...
- BZOJ 2004 公交线路(状压DP+矩阵快速幂)
注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...
- [bzoj 2017] [Usaco2009 Nov]硬币游戏
一个多月没更博客了..(期间明白了自己有多傻逼. 这种问题大概就倒着做... f[i][j]:表示考虑剩下的硬币i..n,且之前的人取了j个时,先手最多拿到的钱数.aft[i]:表示硬币i..n的总钱 ...
- BZOJ.4180.字符串计数(后缀自动机 二分 矩阵快速幂/倍增Floyd)
题目链接 先考虑 假设S确定,使构造S操作次数最小的方案应是:对T建SAM,S在SAM上匹配,如果有S的转移就转移,否则操作数++,回到根节点继续匹配S.即每次操作一定是一次极大匹配. 简单证明:假设 ...
- BZOJ 3231: [Sdoi2008]递归数列 (JZYZOJ 1353) 矩阵快速幂
http://www.lydsy.com/JudgeOnline/problem.php?id=3231 和斐波那契一个道理在最后加一个求和即可 1 #include<cstdio> 2 ...
- BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )
状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...
最新文章
- 阿里云高可用架构之“CDN+WAF+SLB+ECS
- 带你揭秘Web前端发展的前景以及技术
- 处理数字_4_计算某列的总和
- ​知乎700万人围观:如何快速成为数据分析师?
- mysql字段分隔符拆分_面试题Mysql数据库优化之垂直分表
- Spring Boot中使用模板引擎参数化传参数
- Windows下一个可与其他数据集控件结合的通用的搜索框GUSIconEdit
- 限量放送,2018全球智能驾驶峰会「免费拿票攻略」接住了!
- 第十七周项目2-引用作形参
- LeetCode3 无重复字符的最长子串
- 新版鸟哥Linux私房菜资料
- cocos creator如何实现微信好友自定义转发分享功能
- 不为人知的黑科技||双十一薅羊毛正确姿势
- AcWing 138. 兔子与兔子
- Maya---物体跟随曲线动画
- 高等数学学习笔记——第三十二讲——泰勒公式
- 解析json格式请求返回500状态码的异常
- catia 圆显示不圆,设置显示
- 移动应用技术开发大作业——Android平台个人简历
- 大数据的七个核心应用价值
热门文章
- python3android版_Android QPython3 简易 SL4A 服务:android.py
- java构造器调用构造器_java中构造器内部调用构造器实例详解
- netcore开源框架_.NET Core开发精选文章目录,持续更新,欢迎投稿!
- 计算机中丢失ZJCAKeyAdmin,ZJCA数字证书客户端
- html水平分隔线样式,CSS生成漂亮的水平分隔线(horizontal rule)设计效果
- jtoken判断是否包含键_Redis列表键(linkedlist/ziplist)的介绍
- android studio 加载ffmpeg.so,Android studio使用已经编译好的ffmpeg .so库
- 软件设计文档国家标准_GB8567--88
- 干货|SRC漏洞挖掘经验
- java 面试心得总结-BAT、网易