卡常数

题目

在这里插入图片描述
在这里插入图片描述

分析

  • 显然c那么大,绝对是有循环节的,那么这就是一个正解
  • 这个方法还要判断循环节,等等,好多细节滴,我们要更好写的方法!
  • 那么我们可以运用 任 何 一 个 正 整 数 都 可 以 分 解 成 2 的 i 次 幂 之 和 任何一个正整数都可以分解成2的i次幂之和 2i
  • 那么我们就可以运用倍增,在 l o g ( c ) log(c) log(c)的时间呢,完成c次操作。
  • 具体来说定义 g k ( x ) g^k(x) gk(x)为 操作了 2 k 2^k 2k次操作后的结果

题目

做法1

#include<bits/stdc++.h>
using namespace std;
const int g=100005;
int t,c,x,a[5],s,mx,mn,b[g],d,e[g];
int main()
{
	scanf("%d%d",&t,&c);
	memset(e,-1,sizeof(e));
	for(int i=1;i<=t;i++)
	{
		scanf("%d",&x);
		d=0,b[0]=x;
		e[x]=0;
		for(int j=1;;j++)
		{
			s=b[d];
			for(int ff=0;ff<5;ff++)
			{
				a[ff]=s%10;
				s/=10;
			}
			sort(a,a+5);
			mx=a[4]*10000+a[3]*1000+a[2]*100+a[1]*10+a[0];
			mn=a[0]*10000+a[1]*1000+a[2]*100+a[3]*10+a[4];
			b[++d]=mx-mn;
			if(e[b[d]]>=0)
			{
				if(b[e[b[d]]+(c-e[b[d]])%(j-e[b[d]])]==0) puts("00000");
				else printf("%d\n",b[e[b[d]]+(c-e[b[d]])%(j-e[b[d]])]);
				break;
			}
			if(j==c)
			{
				if(b[d]==0) puts("00000");
				else printf("%d\n",b[d]);
				break;
			}
			e[b[d]]=j;
		}
		for(int j=0;j<=d;j++)
			e[b[j]]=-1;
	}
	return 0;
}

做法2

#include <bits/stdc++.h>
using namespace std;
int x, T, tim;
int minn, mamn;
int vis[100002], size[100003], len[100003];
int k;
inline int get(int x) {
    int a[10] = {};
    while (x) {
        a[++a[0]] = x % 10;
        x /= 10;
    }
    while (a[0] != 5) a[++a[0]] = 0;
    sort(a + 1, a + 1 + 5);
    int num = 0;
    for (int i = 1; i <= 5; i++) num = num * 10 + a[i];
    int num1 = 0;
    for (int i = 5; i >= 1; i--) num1 = num1 * 10 + a[i];
    return num1 - num;
}
inline int read() {
    int Num = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        Num = (Num << 1) + (Num << 3) + ch - '0';
        ch = getchar();
    }
    return Num * f;
}
int g[100010][35];
void pre() {
    for (int i = 1; i < 100000; i++) g[i][0] = get(i);
    for (int j = 1; j <= k; j++)
        for (int i = 1; i < 100000; i++) g[i][j] = g[g[i][j - 1]][j - 1];
}
int low[1000];
void last() {
    for (int i = k; i >= 0; i--) {
        if (tim & (1 << i))
            low[++low[0]] = i;
    }
}
int main() {
    T = read(), tim = read();
    k = log(tim) / log(2) + 1;
    pre();
    last();
    while (T--) {
        int x = read();
        for (int i = 1; i <= low[0]; i++) x = g[x][low[i]];
        if (x == 0)
            puts("00000");
        else
            printf("%d\n", x);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值