HOJ3086_Noah's Ark tickets_题解

Brief Description:

一个十进制正整数x,如果x的每一位能整除x的每一位的和,则我们称x为“诺亚数”,现在要求第t个“诺亚数”是多少。

Analysis:

我们先转换一下思路,给出一个数y,如果我们能知道不大于y的“诺亚数”的个数,那么就可以通过二分求出第t个“诺亚数”。

现在把问题转到“给出一个数y,求<=y的诺亚数的个数",

一般求符合某种条件的整数的个数我们都可以用按位DP来做。

设dp[i][j][k][2]:表示前i个数字,数字和为j,最小公倍数为k,最后一维0:没达到上限,1:达到上限

我们有如下转移方程:dp[i+1][j+s][lcm(k,s)] +=dp[i][j][k],(lcm(x,y):求x,y的最小公倍数)

具体按这个方程做就行了,首先要预处理最小公倍数。

细节部分见以下代码:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int lcmz[16];
vectorV;
inline int gcd(int x,int y){
      return x%y==0?y:gcd(y,x%y);
}
int lcm(int x,int y){
    if(x < y) swap(x,y);
    return x/gcd(x,y)*y;
}

int change_int_to_s(int key,char *s){
     // basic coding
     int n = 0;
     char st[16];
     while(key){
        st[n++] = key % 10 + '0';
        key /= 10;
     }
     for(int i=0; i> 1;
            tmp = Solve(mid);
           // printf("l=%d r=%d mid=%d tmp=%d\n",l,r,mid,tmp);
            if(tmp >= t) r = mid;
            else l = mid + 1;
        }
        printf("%d\n",l);
    }

    return 0;
}


你可能感兴趣的:(ACM)