题意: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; }