所谓角谷猜想,即给定一个正整数 n,对 n 反复进行下列两种变换:
1)如果n是偶数,就除以2;
2)如果n是奇数,就乘以3加1。
最后的结果总是1。
我们把从 n 变换到 1 所需要进行的变换次数称做 n 的变换长度,如数字 7 的变换为:
7-22-11-34-17-52-26-13-40-20-10-5-16-8-4-2-1
共进行了 16 次变换,因而 7 的变换长度为 16。
Wish 现在对一个给定区间内的最长变换长度比较感兴趣,但是手算起来计算量太大,于是他又找到了参加信息学竞赛的你,你可以帮助他吗?
每个测试点包含多组数据,第一行一个数 t,表示数据个数。
第二行至第 t+1 行,每行两个数 a、b,表示求 a 和 b 之间数(包含 a、b)的最长变换长度。
输出格式
t 行,每行输出对应输入数据的各个区间的最长变换长度。
2
1 7
9 20
16
20
数据范围
1 <= t <= 100
1 <= a, b <= 10^8
区间长度不超过 10^5
任何一个大于一的自然数,如果是奇数,则乘以三再加一;如果是偶数,则除以二;得出的结果继续按照前面的规则进行运算,最后必定得到一。题目已知这个条件是成立的,所以只要模拟这个过程就行了,循环跳出的条件是“最后得到一”。
记忆化搜索
#include <cstdio> #include <algorithm> #define max(x, y) ((x) > (y) ? (x) : (y)) const int MAXN = 1e8 + 0x1; int t, a, b; int s, dp[MAXN]; int solve(long long x) { if (x == 1) return 0; if (x % 2) return solve(x * 3 + 1) + 1; if (!(x % 2)) return solve(x / 2) + 1; } void dfs(int x) { if (x == b + 1) return; s = max(s, dp[x]); dfs(x + 1); } int main() { scanf("%d", &t); while (t--) { scanf("%d%d", &a, &b); if (a > b) std::swap(a, b); for (int i = a; i <= b; i++) dp[i] = (dp[i] ? dp[i] : solve(i)); s = 0; dfs(a); printf("%d ", s); } return 0; }
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int i;
scanf("%d",&i);
int temp=i;
int count=0;
while(temp-1)
{
if(temp%2==1)
{
count++;
count==1?printf("%d",temp):printf(" %d",temp);//输出要注意,最后一个输出后面不能有空格
temp=temp*3+1;
}
else if(temp%2==0) temp=temp/2;
}
if(count==0) printf("No number can be output !");
printf("
");
}
return 0;
}