一、題目
由4個不同的數字,組成的一個乘法算式,它們的乘積仍然由這4個數字組成。
比如:
210 x 6 = 1260
8 x 473 = 3784
27 x 81 = 2187都符合要求。
如果滿足乘法交換律的算式算作同一種情況,那麼,包含上邊已列出的3種情況,一共有多少種滿足要求的算式。
請填寫該數字,通過瀏覽器提交答案,不要填寫多餘內容(例如:列出所有算式)。
二、思路
暴力枚舉所有四位數,先把乘積的數字中會有重複數位的排除掉,然後記錄每個數位,再來求乘數和被乘數。之後在求乘數和被乘數的時候也要判重複,把數位會重複的數字排除掉。
需要注意的是,只有0123456789十個數字,要求的是一個四位數,那麼最小的是1023,最大的是9876,作爲循環範圍可以縮小範圍。
還有一個需要注意的是,我們在求乘數或被乘數的時候可以用這個乘積的平方根作爲最大限界。
接下來要對乘數和被乘數進行排重:將出現過的數字標記爲1,所以當標記爲0或者2的時候,跳出循環。
三、題解
#include <iostream> #include <algorithm> #include <cmath> using namespace std; int main() { int a,b,c,d; int m,n; int flag; int ans=0; int num[11]; for (int i=1023;i<=9876;i++) { a=i%10;//個位 b=i/10%10;//十位 c=i/100%10;//百位 d=i/1000;//千位 if(a==b || a==c || a==d || b==c || b==d || c==d) //如果數位有重複的就排除掉 { continue; } for (int j=2;j<sqrt(i);j++) //用乘積的平方根作爲最大限界 { memset(num,0, sizeof(num)); num[a]=1; num[b]=1; num[c]=1; num[d]=1; //代表乘積的數字的每個數位已經出現過,標記爲1 if(i%j==0) { flag=1; m=j; n=i/j; while(m) { if(num[m%10]==1) num[m%10]++; else if (num[m%10]==0 || num[m%10]==2) { flag=0; break; } m=m/10; } if(!flag) continue; while(n) { if(num[n%10]==1) num[n%10]++; else if (num[n%10]==0 || num[n%10]==2) { flag=0; break; } n=n/10; } if(flag) { cout << j << "*" << i/j << "=" << i << endl; ans++; } } } } cout << ans << endl; return 0; }
四、結果
6*201=1206
6*210=1260
21*60=1260
15*93=1395
35*41=1435
3*501=1503
3*510=1530
30*51=1530
21*87=1827
27*81=2187
9*351=3159
8*473=3784
12Process finished with exit code 0
故答案是12種方案。但是這種方法速度血媽慢,待優化