题解 P1532 【卡布列克圆舞曲】

· · 题解

这道题有一个很坑的地方:

差不够四位数时补零。

但实际上我们并不需要补零。举个例子,45 是这样变化的:

\begin{aligned} 54-45&=9\\ 9-9&=0\\ 0-0&=0\\ \cdots \end{aligned}

而不是

\begin{aligned} 54-45&=(0)9\\ 90-(0)9&=81\\ 81-18&=63\\ \cdots \end{aligned}

回归正题。这道题就是用while(cin>>n)while(~scanf("%d",&n)读入数据,然后把数字拆开,算出最大值与最小值的差,存入数组。如果发现重复,就把重复的部分输出。

注意,题目说小于maxlongint,但你还是要开long long,不然出现 9876543210-123456789 的情况就爆int了。

下面给出代码:

#include <cstdio>
#include <algorithm>
using std::scanf;
using std::printf;
#define int long long//嫌麻烦可以这样写
#define rep(i,l,r) for(int i=(l),end##i=(r);i<=end##i;i++)
//define的用法,从l到r的循环,其中end##i表示把"end"和i强行以字符串形式拼接
#define dwn(i,l,r) for(int i=(l),end##i=(r);i>=end##i;i--)
//这是上面的rep倒过来
template<class T>//为了能移植使用template
class Vector{//STL的vector常数很大,所以我们手写
    //原理:每次push_back就a[++len],清空len=0,长度就是len,不用担心这个数组会RE或MLE
    private://private,私人的,这些元素不能在外面直接访问
        int len;
        T a[100010];
    public://public,公共的,这些函数可以直接使用
        Vector(){//构造函数,清空
            clear();
        }
        T& operator[](int x){//重载[]运算符,这样就可以访问a数组了
            return a[x];
        }
        void clear(){//清空
            len=0;
        }
        int size(){//长度
            return len;
        }
        void push_back(T x){//push_back
            a[++len]=x;
        }
};
Vector<int> num;//存拆出来的数字
int cha(int a){//把操作封装
    if(a==0) return 0;//特判
    for(num.clear();a;a/=10)
        num.push_back(a%10);//拆数字的简写
    std::sort(&num[1],&num[num.size()+1]);//给数字排序,注意这个+1
    int maxn=0,minn=0;
    rep(i,1,num.size()) minn=minn*10+num[i];
    dwn(i,num.size(),1) maxn=maxn*10+num[i];
    return maxn-minn;
}
int n;
Vector<int> xh;//存循环
signed main(){//#define int long long后就一定要signed main,不然会CE
    while(~scanf("%lld",&n)){//scanf输入不了数时会返回EOF(-1),然而~-1=0
        xh.clear();
        xh.push_back(n);//n也有可能是循环节的一部分
        bool flg=1;
        while(flg){//约等于while(1)不过可以修改flg让它跳出来
            int tmp=cha(xh[xh.size()]);//求差
            xh.push_back(tmp);
            rep(i,1,xh.size()-1){//注意这个-1,新的数不能一起找
                if(xh[i]==tmp){//找到重复的,说明循环的了
                    rep(j,i,xh.size()-1){//输出
                        printf("%lld ",xh[j]);
                    }
                    std::puts(""),flg=0;break;//换行,跳出for和while
                }
            }
        }
    }
    return 0;
}

一 定 要 开 long long!!!

一 定 要 开 long long!!!

一 定 要 开 long long!!!