Hdu 1755A Number Puzzle

Posted on 2009-08-03 22:52  严武  阅读(269)  评论(0编辑  收藏  举报

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

Copyright © 2024 严武
Powered by .NET 9.0 on Kubernetes