/*解题报告
本题思路主要是用余数互补,例如: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