/*解題報告
本題思路主要是用餘數互補,例如:25%8,商為3,餘數為1,也就是說它有3個8,多出一個1,只要它再加上一個7
變成25+7=32就能被8整除,然後我們要用一個HASH[][]2維數組來存放整除和不能整除的數,例如HASH[0][8]表示
存放排列數十進位數除8餘數為0的排列數的十進位數,HASH[1][8]表示存放排列數十進位數除8餘數為1的排列數的
十進位數,以此類推,存放完畢後,就可以直接調用HASH數組即可,當輸入後兩個數,要是12 8,那隻要用12%8,
然後餘數為4,也就是說只要在加上一個4湊合成另外一個8就能被8整除,因此(HASH[0][8]+8)-4,防止HASH[0][8]-4=-1,
所以要加上一個8,接下來輸出結果:hash[((HASH[0][8]+8)-4)%8][8]; 如果hash[((HASH[0][8]+8)-4)%8][8]=0的話就代表
沒有整除的排列十進位數,不為零就是有;((HASH[0][8]+8)-4)%8這一步我想了很久,就是利用餘數互補,例如HASH[0][8]+8==32
那麼32-4==28再%8==4就是我們上面所說要找的湊合成8的最小的排列十進位數,例如再輸入2個數:25 8,25%8餘數為1;
那麼只要加上一個7就湊合成8,((HASH[0][8]+8)-4)%8這步就是找到餘7的最小排列十進位數;
*/
#include <iostream>
#include <cmath>
#include <memory>
#include <algorithm>
#include <vector>
using namespace std;
//int jie[]={0,1,2,6,24,120,720,5040,40320};
int n,m;
int f[10];
int x,k;
int hash[101][101]; //對排列過的數進行HASH
void DP()
{
memset(hash,0,sizeof(hash)); //hash初始化
do //進行全排列工作
{
int t=0;
for(int *i=f; i!=f+n; ++i) //排列的數進行轉換成十進位數
{
t*=10;
t+=*i;
}
if(t)
{
for(int k=1;k<100;++k)
{
if(!hash[t%k][k])
hash[t%k][k] = t; //能整除K和不能整除K的最小的數的餘數儲存起來
}
}
}while(next_permutation(f,f+n)); //直接調用STL裡面的全排列函數
}
int main()
{
int i, j;
while(cin >> n >> m)
{
for(i=0; i < n; i++) { cin >> f[i]; }
sort(f,f+n);
if(!f[0]) //題目要求0不能為首位
{
for(j=1; j<n; j++) { if(f[j]) { swap(f[0],f[j]); break; } } //比零大的數就交換
}
DP();
for(i=1; i<=m; i++)
{
cin >> x >> k;
x %= k;
int t = hash[0][k]+k-x; //要防止t=-1,所以+k
if(!hash[t%k][k]) printf("None/n"); //HASH=0,說明這個數沒有相應的餘數對應相加
else printf("%d/n",hash[t%k][k]);
}
}
return 0;
}
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/yanjiaye520/archive/2009/08/03/4405535.aspx