除数の奇数番号を見つけるプログラム

マヤンク・タクル

2 つの整数 L と R が与えられた場合、L と R の間で約数の約数を持つ整数の数を見つけることが期待されます。

入力フォーマット:

最初の行には、テスト ケースの数である単一の整数 T が含まれています。次の T 行のそれぞれには、i 番目のテスト ケースのパラメーターを示す、スペースで区切られた 2 つの整数 Li と Ri が含まれます。

制約

1≦T≦10000

1≦L≦R≦10^18

#include <stdio.h>

int main(void)
{
    int t;
    long int cnt,countj;
    scanf("%d",&t);
    long long int l[t], r[t];
    int i=0;
    for(i=0;i<t;i++){
        scanf("%d%d",&l[i],&r[i]);
        }

    int div[t];
    for(i=0;i<t;i++){
        //count[i]=0;
        cnt=0;
        for(int j=l[i]+1;j<r[i];j++){
            countj=0;
            for(int k=1;k<=j/2;k++){
                if(j%k==0)
                   countj++;
            }
            if ((countj%2)==0)
            cnt++;
        }
        printf("%ld\n",cnt);
    }
    return 0;
}

このプログラムは実行に時間がかかりすぎます。特に数値が大きい場合、どのように最適化できますか? そして、それはすべてのテスト ケースに合格しませんでしたが、コードのどのようなエラーが考えられますか?

WhozCraig

問題が実際に説明したとおりである場合、パフォーマンスを改善する方法数多くありますが、そのうちの 1 つだけを以下に示しますが、最初に達成しようとしているものの背後にある理論を理解する必要があります。

除数が奇数の整数は、常に完全な二乗です。いくつかの番号が与えられNた場合、X除数があり、いくつかの対応がなければならないYことなどXY=Nも当てはまります。彼らは常にペアで来ます。例外は完全な正方形です。その場合、それらの数にはWなどの約数がありWW=N1 つの約数Wとしてのみカウントされます。したがって奇数の約数があります。N

それで、これはどのように役立ちますか?さて、あなたの述べたタスクは、からすべての整数を見つけることですLを通じてR約数の奇数数を持ちます。しかし、私たちは完全な正方形だけがそのような性質を持っていることを示しました. したがって、その質問が本当に求めていることは次のとおりです。

2 つの整数Lと の間の完全平方の数を見つけますR

そのようなアルゴリズムの 1 つは、単純に次のようなものです。

  • Lテスト番号の浮動小数点平方根取ることから始めます
  • 適切な整数型に変換した後、ルートを二乗します
  • 平方根の二乗が元の数になる場合、完全な二乗です。ループを停止します。
  • それ以外の場合は、テスト番号をインクリメントして再試行してください。停止はあなたが合格した場合R、またはいずれか早い方完璧な広場、見つける最初に

完全な正方形が見つからなかった場合、答えは 0 で終了です。完璧な正方形を見つけた場合、 と の間L徐々にループする必要はなくなりますR開始点 (完全な根) があり、その平方が を超える までその根を徐々に増やしてループしますRこれにより、反復回数大幅に削減されます。

以下のコードでは:

  • T : テストの数
  • L : テストシリーズの最初の数
  • R : テスト シリーズの最後の番号
  • N:奇数除数の値の数との間L及びR 包括的な
  • sr : 検出ループの実行平方根。

コード

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    unsigned int T = 0;
    if (scanf("%u", &T) != 1)
        return EXIT_FAILURE;

    while (T--)
    {
        unsigned int L, R, N=0, sr, i;
        if (scanf("%u %u", &L, &R) != 2)
            return EXIT_FAILURE;

        for (i=L; i<=R; ++i)
        {
            sr = sqrt(i);
            if (sr * sr == i)
                break;
        }

        if (i <= R)
            for (;sr*sr <= R; ++sr,++N);

        printf("%u\n", N);
    }

    return 0;
}

入力

5 
1 2 
10 100
100 1000
500 2500
1 262144

出力

1
7
22
28
512

パフォーマンス

コードが少ないことを考えると、このコードはうまく機能します]。clang 3.9.1 を使用した結果の分解-x c -O2は、立派です。

.LC0:
        .string "%u"
.LC1:
        .string "%u %u"
.LC3:
        .string "%u\n"
main:
        push    rbp
        push    rbx
        xor     eax, eax
        mov     edi, OFFSET FLAT:.LC0
        mov     ebp, 1
        sub     rsp, 40
        lea     rsi, [rsp+20]
        mov     DWORD PTR [rsp+20], 0
        call    __isoc99_scanf
        cmp     eax, 1
        je      .L24
.L1:
        add     rsp, 40
        mov     eax, ebp
        pop     rbx
        pop     rbp
        ret
.L24:
        mov     ebp, eax
        mov     eax, DWORD PTR [rsp+20]
        lea     edx, [rax-1]
        test    eax, eax
        mov     DWORD PTR [rsp+20], edx
        je      .L25
.L3:
        lea     rdx, [rsp+28]
        lea     rsi, [rsp+24]
        xor     eax, eax
        mov     edi, OFFSET FLAT:.LC1
        call    __isoc99_scanf
        cmp     eax, 2
        jne     .L1
        mov     ebx, DWORD PTR [rsp+24]
        cmp     ebx, DWORD PTR [rsp+28]
        jbe     .L10
        jmp     .L11
.L26:
        add     ebx, 1
        cmp     DWORD PTR [rsp+28], ebx
        jb      .L11
.L10:
        pxor    xmm0, xmm0
        mov     eax, ebx
        pxor    xmm2, xmm2
        cvtsi2sdq       xmm0, rax
        ucomisd xmm2, xmm0
        sqrtsd  xmm1, xmm0
        jbe     .L8
        movsd   QWORD PTR [rsp+8], xmm1
        call    sqrt
        movsd   xmm1, QWORD PTR [rsp+8]
.L8:
        cvttsd2si       rax, xmm1
        mov     edx, eax
        mov     ecx, eax
        imul    edx, eax
        cmp     edx, ebx
        jne     .L26
        mov     edi, DWORD PTR [rsp+28]
        cmp     ebx, edi
        ja      .L11
.L12:
        add     eax, 1
        mov     edx, eax
        mov     esi, eax
        imul    edx, eax
        sub     esi, ecx
        cmp     edi, edx
        jnb     .L12
        mov     edi, OFFSET FLAT:.LC3
        xor     eax, eax
        call    printf
.L27:
        mov     eax, DWORD PTR [rsp+20]
        lea     edx, [rax-1]
        test    eax, eax
        mov     DWORD PTR [rsp+20], edx
        jne     .L3
.L25:
        xor     ebp, ebp
        jmp     .L1
.L11:
        xor     esi, esi
        mov     edi, OFFSET FLAT:.LC3
        xor     eax, eax
        call    printf
        jmp     .L27

それでおしまい。それはさらに高速にすることができますが、パフォーマンスのニーズを満たす限り、おそらくそれ以上の努力の価値はありません (したがって、そうであることを願っています) 通常、奇数除数に関する質問は、最小 (または最大) の 1 つの数も要求します。除数の数、それははるかに複雑です。あなたが述べた質問はそれを求めていないため、問題は非常によく軽減されます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

最大の素数除数を見つける(可能な限り最速のプログラム)

分類Dev

2つの数の積を見つけるプログラム

分類Dev

毎月のプログラムで日を見つける

分類Dev

最高の素数を見つけるJavascriptプログラム

分類Dev

PrologでGcdを見つけるためのプログラム

分類Dev

2の補数を見つけるCプログラム

分類Dev

文中の母音と子音を見つけるプログラム

分類Dev

プログラムでAndroidのドット抜けを見つける方法

分類Dev

特定のプログラムを実行しているプログラムを見つける方法は?

分類Dev

Ubuntu Java:特定のプログラムのPIDを見つけてプログラムを強制終了する

分類Dev

プログラムのレンダリングAPIを見つける方法は?

分類Dev

Cプログラムでヒープの破損を見つける

分類Dev

Javaプログラムの時間計算量を見つけるためのプログラム

分類Dev

開いているプログラムのPIDを見つける方法

分類Dev

マシン上のコアの数をプログラムで見つける

分類Dev

プログラムでRの現在のバージョンを見つける

分類Dev

実行中のPythonプログラムのパスを見つける

分類Dev

文中の各単語の文字数を見つけるJavaプログラム

分類Dev

最大の素数を見つけるためのTSQLプログラム

分類Dev

文字列内の最長の単語を見つけるプログラム

分類Dev

数値の平方値を見つけるC ++プログラムの作り方

分類Dev

特定のファイルを作成したプログラムを見つける

分類Dev

リストを使用して0からnまでの「ラッキー」番号を見つけるJavaプログラム

分類Dev

数学的なシリーズの合計をプログラムで見つけるJavaプログラム

分類Dev

「プログラムから開く」リストでプログラムの場所を見つける方法は?

分類Dev

私のプログラムで「constchar * + int」式を見つける方法

分類Dev

Prologプログラムですべての自然数解を見つける

分類Dev

与えられた範囲の回文数を見つけるJavaプログラム

分類Dev

線分とベジェ曲線の交点を見つけるプログラム

Related 関連記事

  1. 1

    最大の素数除数を見つける(可能な限り最速のプログラム)

  2. 2

    2つの数の積を見つけるプログラム

  3. 3

    毎月のプログラムで日を見つける

  4. 4

    最高の素数を見つけるJavascriptプログラム

  5. 5

    PrologでGcdを見つけるためのプログラム

  6. 6

    2の補数を見つけるCプログラム

  7. 7

    文中の母音と子音を見つけるプログラム

  8. 8

    プログラムでAndroidのドット抜けを見つける方法

  9. 9

    特定のプログラムを実行しているプログラムを見つける方法は?

  10. 10

    Ubuntu Java:特定のプログラムのPIDを見つけてプログラムを強制終了する

  11. 11

    プログラムのレンダリングAPIを見つける方法は?

  12. 12

    Cプログラムでヒープの破損を見つける

  13. 13

    Javaプログラムの時間計算量を見つけるためのプログラム

  14. 14

    開いているプログラムのPIDを見つける方法

  15. 15

    マシン上のコアの数をプログラムで見つける

  16. 16

    プログラムでRの現在のバージョンを見つける

  17. 17

    実行中のPythonプログラムのパスを見つける

  18. 18

    文中の各単語の文字数を見つけるJavaプログラム

  19. 19

    最大の素数を見つけるためのTSQLプログラム

  20. 20

    文字列内の最長の単語を見つけるプログラム

  21. 21

    数値の平方値を見つけるC ++プログラムの作り方

  22. 22

    特定のファイルを作成したプログラムを見つける

  23. 23

    リストを使用して0からnまでの「ラッキー」番号を見つけるJavaプログラム

  24. 24

    数学的なシリーズの合計をプログラムで見つけるJavaプログラム

  25. 25

    「プログラムから開く」リストでプログラムの場所を見つける方法は?

  26. 26

    私のプログラムで「constchar * + int」式を見つける方法

  27. 27

    Prologプログラムですべての自然数解を見つける

  28. 28

    与えられた範囲の回文数を見つけるJavaプログラム

  29. 29

    線分とベジェ曲線の交点を見つけるプログラム

ホットタグ

アーカイブ