BZOJ 1183 Croatian2008 Umnozak

来源:互联网 发布:高性能网络编程 陶辉 编辑:程序博客网 时间:2024/04/30 10:15

提示:
1. 一个数的Digit-Product能够是什么样的数。
2. 这些数数量有多少呢?

详细题解在代码后:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <vector>#include <deque>#include <stack>#include <queue>#include <set>#include <map>#include <algorithm>using namespace std;typedef long long ll;const ll lim = 1000000000000000000LL;const ll limh = 1000000000;__inline ll ceil( ll a, ll b ) { return (a+b-1)/b; }__inline ll floor( ll a, ll b ) { return a/b; }ll a , b , res = 0;int k[4];const int num[]={2,3,5,7};int dig[10][4];ll d[20][30][20][20][20];ll dp(int bit , ll a , ll pos , ll l , ll r){    ll b = a+pos-1;    if(a>r || b<l) return 0;    if(bit==18) return !k[0] && !k[1] && !k[2] && !k[3];//  cout<<bit<<" "<<a<<" "<<pos<<" "<<l<<" "<<r<<endl;    bool memerizeAble = (l<=a && b<=r) ; // Arbitrary process    ll &now = d[bit][k[0]][k[1]][k[2]][k[3]] , res = 0;    if(memerizeAble && now>=0) return now;    pos/=10;    for(int i=(a!=0);i<10;i++)     {        bool ok = true;        for(int j=0;j<4;j++) ok &=  k[j]>=dig[i][j];        if(!ok) continue;        for(int j=0;j<4;j++) k[j] -= dig[i][j];        res+= dp(bit+1, a+pos*i, pos, l, r);        for(int j=0;j<4;j++) k[j] += dig[i][j];    }    if(memerizeAble) now = res;    return res;}void dfs(ll now , int d){    if(now>limh || now*now > b)  return;    if(d==4)     {        res+= dp(0, 0, lim, ceil(a , now), floor(b, now));        return ;    }    dfs(now, d+1);    k[d]++;    dfs(now*num[d], d);    k[d]--;}int main(int argc, char *argv[]) {    memset(d, -1, sizeof(d));    for(int i=1 , _i=1;i<10;i++ , _i=i) for(int j=0;j<4;j++) while(_i%num[j]==0) _i/=num[j] , dig[i][j]++;    cin>>a>>b;    dfs(1, 0);    cout<<res<<endl;    return 0;}

Self-Product只能是2 , 3 , 5 , 7的倍数。 那么其实枚举这些取值是不难做到的。 然后数位DP一下就好。

注意:
由于这里要查询多次 , 所以这里要考虑记录一些通用的答案 , 也就是对于选择没有限制的答案。

0 0
原创粉丝点击