藍橋杯 21位花數
阿新 • • 發佈:2019-01-12
題意
一個21位的數,每一位的21次方之和,等於該數本身,
求所有這樣的21位數
思路來源
https://blog.csdn.net/t51645/article/details/55057082
題解
類似整數劃分,0-9這10個數,分21位數,
所有可能是C(30,9)=14307150個
驗證和是否在1e20-(1e21-1)之間,
然後再判斷和與列舉的個數是否相等。
自己寫了一發大數
O(n²)的乘法
256s才跑出來GG
最後答案只有兩個
128468643043731391252
449177399146038697307
將21位分成三段,用陣列維護,就會省不少時間
具體寫法回頭再補,眼下能做就是了QAQ
程式碼
粘一發自己的大數辣雞程式碼好了
#include <iostream> #include <algorithm> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <bitset> const int INF=0x3f3f3f3f; const int MOD=1e9+7; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<int,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn=2500; struct BigInt { const static int mod=10000; const static int LEN=4; int a[maxn],len; int num[10]; BigInt() { memset(a,0,sizeof(a)); len=1; } void init(int x) { memset(a,0,sizeof(a)); len=0; do//四位一存 如123456789存為 6789 2345 1 { a[len++]=x%mod; x/=mod; }while(x); } void Init(const char s[])//重點 123 4567 { memset(a,0,sizeof(a)); int l=strlen(s),res=0; len=l/LEN; if(l%LEN)len++;//l/LEN向上取整 len=2 表明需要兩個位元組能存下 for(int i=l-1;i>=0;i-=LEN) { int t=0,k=max(i-LEN+1,0);//k是找到當前位元組的最高位 回退len-1長 防越界 for(int j=k;j<=i;j++)t=t*10+s[j]-'0';//從4開始 t臨時儲存4567 a[res++]=t;//將低位存入 } } int Compare(const BigInt &b)//位多的大 { if(len<b.len)return -1; if(len>b.len)return 1; for(int i=len-1;i>=0;i--)//從高位比較 if(a[i]<b.a[i])return -1; else if(a[i]>b.a[i])return 1; return 0;//完全相等的情況 } BigInt operator +(const BigInt &b)const { BigInt ans; ans.len=max(len,b.len); for(int i=0;i<=ans.len;i++)ans.a[i]=0; for(int i=0;i<ans.len;i++) { ans.a[i]+=((i<len)?a[i]:0)+((i<b.len)?b.a[i]:0);//防止越位現象 ans.a[i+1]+=ans.a[i]/mod;//向高位進位 ans.a[i]%=mod; } if(ans.a[ans.len]>0)ans.len++;//產生了9999+9999=9998 1的陣列高位進位 return ans; } BigInt operator -(const BigInt &b)const//確保被減數大 差為正 { BigInt ans; ans.len=len; int k=0; for(int i=0;i<ans.len;i++) { ans.a[i]=a[i]+k-b.a[i]; if(ans.a[i]<0)ans.a[i]+=mod,k=-1;//向a[i]高位借10000,k=-1下輪生效 else k=0; } while(ans.a[ans.len-1]==0&&ans.len>1)ans.len--;//把字首0去掉 如果ans.len=1時說明a=b差為0 return ans; } BigInt operator *(const BigInt &b)const { BigInt ans; for(int i=0;i<len;i++) { int k=0; for(int j=0;j<b.len;j++) { int temp=a[i]*b.a[j]+ans.a[i+j]+k;//模擬小學生乘法 i*j加到i+j上去 k為低位來的進位 ans.a[i+j]=temp%mod; k=temp/mod;//k為向高位進的位 下一輪生效 } if(k!=0)ans.a[i+b.len]=k;//高位進位 99*99=9801 右起第1位*右起第1位還是能到右起第3位的 } ans.len=len+b.len;//4位數*4位數不會超過8位數 while(ans.a[ans.len-1]==0&&ans.len>1)ans.len--;//查出實際長度 return ans; } BigInt operator /(const int &n)const//被確保被除數大 商為正 { BigInt ans; ans.len=len; int k=0; for(int i=ans.len-1;i>=0;i--) { k=k*mod+a[i];//k=上一位來的退位*10000+這一位 ans.a[i]=k/n;//這一位除以n k=k%n;//這一位除以n的餘數送給下一位,i=0最後一位如57/28餘的1直接丟掉 取整 } while(ans.a[ans.len-1]==0&&ans.len>1)ans.len--; return ans; } ll operator %(const int &n)const { ll ans=0; for(int i=len-1;i>=0;i--) { ans=ans*mod+a[i]; if(ans>n)ans%=n; } return ans; } void cal() { memset(num,0,sizeof(num)); num[a[len-1]%10]++; for(int i=len-2;i>=0;--i) { int tmp=a[i]; num[tmp%10]++; num[tmp/10%10]++; num[tmp/100%10]++; num[tmp/1000]++; } } void output() { printf("%d",a[len-1]);//是多少就是多少 沒有字首0 for(int i=len-2;i>=0;i--) printf("%04d",a[i]);//包含字首0 如0001 printf("\n"); } }; char s[maxn]; ll t[11],cnt; int step[10]; BigInt tmp[10]; BigInt low,high,ten,one,a[11],b[11],cal,ans[maxn]; void dfs(int pos,int num) { if(pos==10) { cal.init(0); for(int i=0;i<10;++i) { tmp[i].init(step[i]); cal=cal+tmp[i]*a[i]; } if(!(cal.Compare(low)>=0&&cal.Compare(high)<=0))return; cal.cal(); for(int i=0;i<10;++i) { if(step[i]!=cal.num[i])return; } ans[cnt++]=cal; return; } if(pos<=7&&!num)return; if(pos==9) { step[pos]=num; dfs(pos+1,0); } else { for(int i=0;i<=num;++i) { step[pos]=i; dfs(pos+1,num-i); } } } int main() { one.init(1); ten.init(10); low.init(1); high.init(1); for(int i=0;i<=9;++i) { t[i]=i*i*i; b[i].init(t[i]); } for(int i=1;i<21;++i)low=low*ten; high=low;high=high*ten;high=high-one; low.output(),high.output(); for(int j=0;j<=9;++j) { a[j].init(t[j]*t[j]*t[j]); a[j]=a[j]*a[j]; a[j]=a[j]*b[j]; a[j].output(); } dfs(0,21);//當前位置,還剩多少個數字 for(int i=0;i<cnt;++i) ans[i].output(); return 0; }