XTU 洗纸牌问题
来源:互联网 发布:淘宝创业成功案例 编辑:程序博客网 时间:2024/04/30 05:28
纸牌
题目描述
有2N张纸牌,标号从1到2N。一次洗牌,可以将牌的排列改成n+1,1,n+2,2,...,n,2n。请问这样洗牌几次,可以让牌回到原始的状态。比如N=2时,1234->3142->4321->2413->1234 一共洗4次。输入
每行输入一个整数N(1≤N≤10,000),N如果为0,表示输入结束,不需要处理。输出
每行输出一个样例的结果。样例输入
12
3
4
5
6
0
样例输出
24
3
6
10
12
分析:
题目给的N达到了100,000,一般的方法极有可能超时。
下面是最先想到的成功超时的方法:
方法一(极有可能超时)
#include <iostream>//1210 Eddy's 洗牌问题 模拟 #include <string> using namespace std; int n,m; void change(string &str ) { string a; for(int i=1;i<=n;i++) { cc++; a=str[n+i]; str.erase(n+i,1); str.insert(i*2-1,a); } } int main() { string str,tmpstr; while(cin>>n) { str.resize(n*2+1); for(int i=1;i<=n*2;i++) str[i]=i+'0'; m=0; tmpstr=str; while(1) { change( str ); m++; if(tmpstr==str) break; } cout<<m<<endl; } return 0; }
规律就是1的位置,很容易发现1的位置是从1->2->4->8……如果超过数尾则从头偏移,总之只要经过若干次移动,1再次移动在1的位置,就能够保证洗牌洗回了原序列。
方法二(简单)
#include<bits/stdc++.h>using namespace std;int main(){ int n; while(scanf("%d",&n),n) { int cnt=0; int pos=1; do { if(pos<=n) pos*=2;//记录1的位置:1-2-4-8-...直到01串尾 else pos=(pos*2-1)%(2*n);//相当于环形存储(求余操作) cnt++; } while(pos!=1); printf("%d\n",cnt); } return 0;}
【另】
当然方法不止这些!比如这种,只追踪第一张牌的位置,只有当他在第n+1的位置时下一次才会回到初始位置.你并没有考虑其他牌的位置,因为他们都是相关的,位置不会乱.#include <stdio.h>int main(){ int n, x, c; for(; scanf("%d", &n) != EOF; printf("%d\n", c)) for(c = x = 1; (x = x>n ? (x-n)*2-1 : x*2) - 1; c++); return 0;}
--------------------
【附:一文一图】
阅读全文
0 0
- XTU 洗纸牌问题
- 纸牌问题。。。
- 纸牌问题
- 猜纸牌问题
- 均分纸牌问题
- 问题 G: 均分纸牌
- 纸牌博弈问题
- 纸牌博弈问题
- UVA10935纸牌问题
- 纸牌博弈问题
- 纸牌博弈问题
- 纸牌博弈问题
- 纸牌博弈问题
- 纸牌三角形问题
- 发纸牌问题---多维数组
- 纸牌博弈问题 动态规划
- 洗纸牌算法
- 纸牌
- 1061. Dating (20)
- CopyPNGFile 异常错误
- Linux运维学习之路(4)Linux文件管理
- 前言的闲话以及第一章的入门(四).2
- kolakoski序列
- XTU 洗纸牌问题
- 动态代理模式
- 面试题总结——JAVA高级工程师
- bzoj #1101 ZAP-Queries (莫比乌斯反演)
- 滑雪 POJ
- 2017书单3
- Java开发笔试题集
- Swift 不使用 main storyBoard
- hdu 1225