これは数学関連の質問でもありますが、C++ で実装したいと思います...そのため、フォーム2^n
に数値があり、その桁の合計を計算する必要があります (基数 10;P )。私の考えは、次の式で計算することです。
sum = (2^n mod 10) + (floor(2^n/10) mod 10) + (floor(2^n/100) mod 10) + ...
すべての桁について: floor(n/floor(log2(10)))
.
第1項はべき乗剰余で簡単に計算できるのですが、それ以外は困っています。は大きいのでn
、大きな整数ライブラリを使用したくないため、pow(2,n)
モジュロなしでは計算できません。第 1 項のコード スニペット:
while (n--){
temp = (temp << 1) % 10;
};
しかし、2番目にはわかりません。floor
「0」(2/10)になるため、個別に指定することもできません。これを達成することは可能ですか?(http://www.mathblog.dk/project-euler-16/より簡単な解決策。)もちろん、この方法で実行できない場合は、他の方法を探します。(たとえば、リンクのコメントのように、数字をバイト配列に格納します)。
編集:既存の回答に感謝しますが、数学的に解決する方法を探しています。bignum や digit-vector なしで実装できる 1 つのアイデアを思いついたので、それが機能するかどうかをテストします。
したがって、合計については上記の式があります。しかし、どちらが2^n/10^k
のように書くことができます。次に、小数部分とその整数部分を取り、整数部分で剰余累乗を行います。最後の反復の後、10 を法とする分数も掛けます。うまくいかない場合、または上記のアイデアのどこかが間違っている場合は、ベクトル ソリューションに固執し、答えを受け入れます。2^n/2^(log2 10^k)
2^(n-k*log2 10)
2^(n-k*log2 10) = 2^(floor(n-k*log2 10)) * 2^(fract(n-k*log2 10))
編集:わかりました、非整数モジュロで剰余べき乗を行うことはできないようです(?)(または私はそれについて何も見つけていません)。だから、私は数字/ベクトルベースのソリューションをやっています。
コードが完全に機能しません!
適切な値が得られません: (1366 ではなく 1390):
typedef long double ldb;
ldb mod(ldb x, ldb y){ //accepts doubles
ldb c(0);
ldb tempx(x);
while (tempx > y){
tempx -= y;
c++;
};
return (x - c*y);
};
int sumofdigs(unsigned short exp2){
int s = 0;
int nd = floor((exp2) * (log10(2.0))) + 1;
int c = 0;
while (true){
ldb temp = 1.0;
int expInt = floor(exp2 - c * log2((ldb)10.0));
ldb expFrac = exp2 - c * log2((ldb)10.0) - expInt;
while (expInt>0){
temp = mod(temp * 2.0, 10.0 / pow(2.0, expFrac)); //modulo with non integer b:
//floor(a*b) mod m = (floor(a mod (m/b)) * b) mod m, but can't code it
expInt--;
};
ldb r = pow(2.0, expFrac);
temp = (temp * r);
temp = mod(temp,10.0);
s += floor(temp);
c++;
if (c == nd) break;
};
return s;
};