哈理工第六屆程序設計團隊賽 E Mod

http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2318

problem E . Mod

TimeLimit: 1000ms  Memory Limit: 100000k

Description

Kim剛剛學會C語言中的取模運算(mod)。他想要研究一下一個數字A模上一系列數後的結果是多少。幫他寫個程序驗證一下。

Input

          第一行一個整數T代表數據組數。

          接下來T組數據,第一行一個整數n,接下來n個數字ai

          接下來一行一個整數m,接下來m個數字bi

Output

對於每個bi,輸出bi%a1%a2%...%an

Sample

Input

Output

1

4

10 9 5 7

5

14 8 27 11 25

4

3

2

1

0


Hint

在C語言中,A mod B 是 a%b

樣例解釋:

14%10%9%5%7=4

8%10%9%5%7=3

...

數據範圍:

1<=n<=100000

1<=m<=100000

1<=ai<=1000000000

0<=bi<=1000000000


開始以爲是用什麼高端的數論算法,想了很久沒想到,換了個姿勢,找一找規律沒想到就a了...

規律: mod[i]這個序列一定要是遞減的,而且相鄰的兩個數不能互爲倍數 ,

mod[0]是mod序列的循環節,


遞減是因爲如果前面已經MOD了一個小數,那後面這個大一點的MOD肯定對結果沒有任何影響

如果前面一個數是12,那麼緊鄰的後一個數不能是2,3,4,6,之中的任何一個數,如果是就用後面的數把12替換掉

這樣就化簡了很多mod[i], 接下來找循環節就行了,很顯然循環節就是化簡後的mod[0],

有了循環節,後面計算肯定有重複,就用map把算過的記錄一下就好了


#include <cstdio>
using namespace std;
int mod[100050];
map<int,int>ans;
int main(){
    
    int t, n ,m ; 
    scanf("%d",&t);
    while ( t-- ){
    
        scanf("%d",&n);
        int x,idx = 0;

        scanf("%d",mod);  n--;
        while ( n--){
            scanf("%d",&x);
            if( x < mod[idx] ){
                while ( mod[idx] % x == 0 ) idx--;
                mod[++idx] = x;
            }
        }
//        for (int i = 0;i < idx;++i )
//            cout <<mod[i]<<" ";cout <<endl;
        scanf("%d",&m);
        ans.clear();
        int tx;
        while ( m-- ){
            scanf("%d",&tx);
            if ( ans.find(tx%mod[0]) != ans.end() )
                printf("%d\n",ans[ tx%mod[0] ]);
            else {
                x = tx;
                for (int i = 0 ;i <= idx;++i)
                    x %= mod[i];
                ans[tx%mod[0]] = x;
                printf("%d\n",x);
            }
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章