数论-魔幻六位数

http://prayer.hustoj.com/problem.php?id=1733
感觉就是很难的那种题;
网上搜不到题解;
自己又笨;
只能到处问大神;
我直接说思路了;


显然的,我们发现暴力很萎;
虽然可以剪枝,但太复杂;
我们就枚举最后一位,因为最后一位一定不会进位,所以我们就可以得出所有的数字了;
然后是轮换排列,所以每个位子上会每个数会出现一次;
那我们把枚举最后一位时所得到的一组数字加起来;
这个值再乘以11111..;
我们就得到了把轮换的那几个数字全部加起来所的的结果;
比如:
142857+428571+285714+…=(1+4+2+8+5+7)*111111
然后我们可以判断一下这个结果能否整除(1+2+…+m)
可以整除的话那我们就得到一个解,再判断一下这个解的各位数字是不是原来算出来的那组数字;
是的话就是了;
关于进制的问题瞎搞就好啦;
比如那个111111是n进制的;

#include<iostream>
#define Ll long long
using namespace std;
Ll n,m,a[20],q[20],tot;
bool b[20];
char s[26]="0123456789ABCDEF";
Ll turn(Ll x){
    Ll ans=0,k=1;
    while(x){ans+=(x%10)*k;k*=n;x/=10;}
    return ans;
}
void pd(Ll x){
    Ll sum=0,y=0;
    for(int i=1;i<=m;i++){y=x*i%n;sum+=y;a[i]=y;b[i]=0;}
    y=1;
    for(int i=1;i<m;i++)y=y*10+1;
    y=turn(y)*sum;
    if(y%(m*(m+1)/2))return;
    y/=m*(m+1)/2;
    tot=0;
    while(y)q[++tot]=y%n,y/=n;  
    if(tot!=m)return;
    for(int i=1;i<=m;i++){
        bool p=0;
        for(int j=1;j<=m;j++)if(a[j]==q[i]&&!b[j]){b[j]=1;p=1;break;}
        if(!p)return;
    }
    while(tot)cout<<s[q[tot--]];
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<n;i++)pd(i);
}

话说阳哥的代码又快又小又短
这里写图片描述

posted @ 2017-03-12 13:29  largecube233  阅读(154)  评论(0编辑  收藏  举报