タイトルの説明
1~13
整数の1の出現数を見つけて、整数100~1300
の1の出現数を計算しますか?このため、1〜13の1を1、10、11、12、13と数え、計6回出現したが、後者の問題は正しかった。ACMerはあなたが彼を助けて問題をより一般的にすることを望んでいます負でない整数間隔(1からnまでの1の発生数)で1の発生数をすばやく見つけることができます。
問題解決のアイデア
主なアイデア:
整数ポイント(1、10、100など)を位置ポイントi(nビット、数十、数百などに対応)として設定し、それぞれに1が含まれるポイントの数を分析する
- 設定された整数の位置に従って、nを除算し、2つの部分に分割します(高
n/i
ビット、低ビット)。n%i
- iが100桁を表し、100桁に対応する数が> = 2、たとえばn = 31456、i = 100、a = 314、b = 56の場合、100桁が1である回数は、a / 10 + 1 = 32になります。 (最大2桁の0〜31)、毎回100の連続したポイントが含まれます。つまり、(a%10 + 1)* 100桁の1の100ポイントがあります。
- iが100桁を表し、100桁に対応する数が1である場合(n = 31156、i = 100、a = 311、b = 56など)、100桁は1に対応し、a%10(最も高い2ビット0〜30)には100個の連続したポイントが含まれます。上位2桁が31(つまり、a = 311)の場合、この時間はローカルポイント00〜56にのみ対応し、合計でb + 1回、すべてのポイントが(a% 10 * 100)+(b + 1)、これらの数百の点は1に対応します
- iが100を表し、100に対応する数が0の場合、たとえばn = 31056、i = 100、a = 310、b = 56の場合、100が1である回数は、a / 10 = 31(最も高い2ビット0〜30)
- 上記の3つの状況に基づいて、100桁が0または> = 2に対応する場合、(a + 8)/ 100はすべての100ポイントを含めて10回あり、100桁が1(a%10 == 1)の場合、増やす必要があります。ローカルポイントb + 1
- 8が追加される理由は、100の位が0の場合、a / 10 ==(a + 8)/ 10、100の位> = 2の場合、8はキャリーを生成し、効果は(a / 10 + 1 )
コードの実装
int NumberOf1Between1AndN_Solution(int n)
{
int ones = 0;
for (long long m = 1; m <= n; m *= 10)
{
int a = n/m, b = n%m;
if(a%10 == 0)
ones += a / 10 * m;
else if(a%10 == 1)
ones += (a/10*m) + (b+1);
else
ones += (a/10+1)* m;
}
return ones;
}