题目1033:继续xxx定律
时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:5990
解决:1470
-
题目描述:
-
当n为3时,我们在验证xxx定律的过程中会得到一个序列,3,5,8,4,2,1,将3称为关键数,5,8,4,2称为覆盖数。现在输入n个数字a[i],根据关键数与覆盖数的理论,我们只需要验证其中部分数就可以确定所有数满足xxx定律,输出输入的n个数中的关键数。如果其中有多个关键数的话按照其输入顺序的逆序输出。
-
输入:
-
输入数据包含多个用例,每个用例首先包含一个整数n,然后接下来一行有n个整数a[i],其中: 1<=n<=500, 1<a[i]<=1000
-
输出:
-
请计算并输出数组a中包含的关键数,并按照其输入顺序的逆序输出,每个用例输出占一行。
-
样例输入:
-
3 3 8 4 5 3 8 4 7 15 5 3 8 4 15 7 0
-
样例输出:
-
3 15 7 3 7 15 3
-
答疑:
- 解题遇到问题?分享解题心得?讨论本题请访问: http://t.jobdu.com/thread-7757-1-1.html
- 思路:说实话开始没有看懂什么意思,但是因为这一题是联系 题目1031:xxx定律得来的。
- 具体做法就是建立一个标记数组,用来对覆盖数就行标记,如果num_outpu[index]=1,标明对对应是覆盖数,就不予输出。我这里有个题目条件没有利用,也就是开了一个1000000很大的数组,其实只需要关注1~1000即可,也即1<a[i]<=1000。后面给出别人的代码考虑了
-
#include<iostream> #include<cstring> #include<fstream> using namespace std; int num[501]; int num_output[1000000]; int main() { ifstream in; in.open("3.txt"); int n; while(in>>n && n!=0) { memset(num_output,0,sizeof(num_output)); num_output[1]=1; for(int i=0;i<n;++i) { in>>num[i]; int temp=num[i]; while(temp!=1) { if(temp%2==0) { temp=temp/2; num_output[temp]=1; }else { temp=(3*temp+1)/2; num_output[temp]=1; } } } int index; for(int i=0;i<n;++i)//寻找最后一个关键数的标记 if(num_output[num[i]]==0) { index=i; break; } for(int i=n-1;i>=index+1;--i) { if(num_output[num[i]]!=1) cout<<num[i]<<" "; } cout<<num[index]; cout<<endl; } return 0; }
-
(2)
题目的主要思路:先定义一个大小为1001的数组mark,然后将每一个输入数字所产生的覆盖数字(小于1001,大于1001的不需要标记)都标记为1,例如如果输入数字是3,则mark[5]=1,mark[8]=1,mark[4]=1,mark[2]=1,mark[1]=1。最后对于每一个输入的数字a[i]检查mark[a[i]]的值是否为0,如果为0则将a[i]输出。
剪纸操作:在对每一个输入的数字进行操作之前可以先判断该数字是否为别的数字的覆盖数,如果为别的数字的覆盖数则可以跳过,直接检查下一个数字。
-
#include<stdio.h> #include<string.h> int key[1000000];//关键数 key数组要开的尽量大 int main(){ int i,n,temp; int a[100000]; //freopen("C:\\Users\\SJF\\Desktop\\acm.txt","r",stdin); while(scanf("%d",&n) != EOF && n != 0){ //输入数据 for(i = 0;i < n;i++){ scanf("%d",&a[i]); } memset(key,0,sizeof(key)); for(i = 0;i < n;i++){ temp = a[i]; //求解覆盖数,标记为1 while(temp != 1){ //如果是偶数,就把temp砍掉一半 if(temp % 2 == 0){ temp = temp / 2; } //如果是奇数,把temp变成 3*temp+ 1后砍掉一半 else{ temp = (temp * 3 + 1) / 2; } //出现在求解序列中标记为1 key[temp] = 1; }//while }//for int flag = 0; //逆序输出关键数(序列中没有标记为1的即为关键数) for(i = n-1;i >= 0;i--){ if(key[a[i]] == 0){ if(flag == 1){ printf(" "); } printf("%d",a[i]); flag = 1; } } printf("\n"); } return 0; }
(3)数据结构set的使用 -
#include <iostream> #include <fstream> #include <set> using namespace std; const int N = 1000 + 10; int main() { int n; int a[N]; #ifndef ONLINE_JUDGE ifstream cin("d:\\OJ\\uva_in.txt"); #endif // ONLINE_JUDGE while (cin >> n) { if (n == 0) break; set<int> s; for (int i = 0; i < n; i++) { cin >> a[i]; int x = a[i]; while (x != 1) { if (x & 1) { x = (3 * x + 1) / 2; s.insert(x); } else x /= 2; s.insert(x); } } bool first = true; for (int i = n - 1; i >= 0; i--) { if (s.count(a[i]) <= 0) { if (first) first = false; else cout << " "; cout << a[i]; } } cout << endl; } return 0; }