题意:n<=1e9
1,2,3,4,5,6.。。n
问你有多少个数字集合,不包含重复的数位
好题
数位dp 预处理 cnt【state】,然后背包
注意11这种,本身重复的也不行
ps:看了下别人的代码,好像满足条件的数并不太多,直接暴力dfs处理出cnt数组也可以
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <ctime>
using namespace std;
class LittleElephantAndSubset
{
public:
int getNumber(int N);
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = 3; int Arg1 = 7; verify_case(0, Arg1, getNumber(Arg0)); }
void test_case_1() { int Arg0 = 10; int Arg1 = 767; verify_case(1, Arg1, getNumber(Arg0)); }
void test_case_2() { int Arg0 = 47; int Arg1 = 25775; verify_case(2, Arg1, getNumber(Arg0)); }
void test_case_3() { int Arg0 = 4777447; int Arg1 = 66437071; verify_case(3, Arg1, getNumber(Arg0)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main()
{
LittleElephantAndSubset ___test;
___test.run_test(-1);
return 0;
}
// END CUT HERE
int cnt[1024];
bool vis[10];
int dig[15];
int dp[15][1024];
int now;
int dfs(int len,bool lim,bool pos,int state) {
if(!len) return pos && state == now;
if(!lim && pos && dp[len][state] != -1) return dp[len][state];
int mx = lim ? dig[len-1] : 9;
int ret = 0;
for(int i = 0; i <= mx; i++) {
if(vis[i]) {
int tmp ;
if(state & (1<<i)) continue;
if(!pos && !i) tmp = state;
else tmp = state | (1<<i);
ret += dfs(len-1,lim&&i==mx,pos||i,tmp);
}
}
if(!lim && pos) dp[len][state] = ret;
return ret;
}
long long f[1024];
int LittleElephantAndSubset::getNumber(int N)
{
int tot = 0;
for(int t = N; t; t /= 10) dig[tot++] = t%10;
memset(cnt,0,sizeof(cnt));
for(int i = 0; i < 1024; i++) {
memset(vis,false,sizeof(vis));
vis[0] = true;
for(int j = 0; j < 10; j++) if(i >> j & 1) {
vis[j] = true;
}
now = i;
memset(dp,-1,sizeof(dp));
cnt[i] = dfs(tot,true,false,0);
}
memset(f,0,sizeof(f));
f[0] = 1;
for(int state = 1; state < 1024; state++) if(cnt[state]){
for(int i = 0; i < 1024; i++)if(!(i&state)) {
f[i|state] +=( f[i] * cnt[state]%1000000007 );
f[i|state] %= 1000000007;
}
}
int ans = 0;
for(int i = 1; i < 1024; i++) {
ans += f[i];
if(ans >= 1000000007) ans -= 1000000007;
}
return ans;
}