SRM 597 Div 2 1000 LittleElephantAndSubset

Problem Statement

 

Little Elephant from the Zoo of Lviv has a set S. The set S contains the integers 1, 2, 3, ...,N. He considers some non-empty subset of S cool if we can write down all elements of the subset by using each of the digits 0-9 at most once.

Examples: The subsets {12,345,67890} and {47,109} are cool. The subset {147,342} is not cool because the digit 4 is used twice. The subset {404} is not cool for the same reason.

You are given the int N. Let X be the total number of non-empty cool subsets of S. Return the value (X modulo 1,000,000,007).

Definition

 
Class: LittleElephantAndSubset
Method: getNumber
Parameters: int
Returns: int
Method signature: int getNumber(int N)
(be sure your method is public)
 
 

Constraints

- N will be between 1 and 1,000,000,000 (10^9), inclusive.

Examples

0)  
 
3
Returns: 7
All 7 non-empty subsets are cool in this case:
  • {1, 2, 3}
  • {1, 2}
  • {1, 3}
  • {2, 3}
  • {1}
  • {2}
  • {3}
1)  
 
10
Returns: 767
In this case, the total number of non-empty subsets is 2^10-1 = 1023. The only not cool subsets are those that contain both 1 and 10. There are 2^8 = 256 of them. Thus, the answer is 1023-256 = 767.
2)  
 
47
Returns: 25775
3)  
 

4777447
Returns: 66437071

数位DP,先预处理出cnt[S]表示选0..9状态为S时能够得到的不超过N的数字个数(不能有前导0)。

注意数字本身也不能有重复数字。

然后就是背包。

F[S]=状态为S时{1,2,3,...N}的子集数。

状态转移方程:F[i|S]+=F[i]*cnt[S];    i&S==0

ANS=SIGMA(F[S])    S>0

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;
#define ll long long
const int mod=1e9+7;
int cnt[1884];
bool vis[33];
int bit[334];
int dp[22][3322];
int now;
int dfs(int len,int s,bool lim,bool pos)
{
    if(!len)return pos&&s==now;
    if(!lim&&pos&&dp[len][s]!=-1)return dp[len][s];
    int ed=lim?bit[len-1]:9;
    int ans=0;
    for(int i=0;i<=ed;i++)
    {
        if(vis[i])
        {
            if(s&(1<<i))continue;
            int news;
            if(!pos&&!i)news=s;
            else news=s|(1<<i);
            ans+=dfs(len-1,news,lim&&i==ed,pos||i);
        }
    }
    if(!lim&&pos)dp[len][s]=ans;
    return ans;
}
ll f[2334];
class LittleElephantAndSubset {
public:
	int getNumber(int);
}test;

int LittleElephantAndSubset::getNumber(int N) {
    int tot=0;
    for(int t=N;t;t/=10)bit[tot++]=t%10;
    memset(cnt,0,sizeof cnt);
    for(int i=0;i<1024;i++)
    {
        memset(vis,0,sizeof vis);
        vis[0]=1;
        for(int j=0;j<10;j++)if(i>>j&1)vis[j]=1;
        now=i;
        memset(dp,-1,sizeof dp);
        cnt[i]=dfs(tot,0,1,0);  ///int dfs(int len,int s,bool lim,bool pos)
    }
    memset(f,0,sizeof f);
    f[0]=1;
    for(int s=1;s<1024;s++)if(cnt[s])
    {
        for(int i=0;i<1024;i++)if(!(i&s))
        {
            f[i|s]+=(f[i]*cnt[s]%mod);
            f[i|s]%=mod;
        }
    }
    int ans=0;
    for(int i=1;i<1024;i++)
    {
        ans+=f[i];
        if(ans>=mod)ans-=mod;
    }
    return ans;
}
int main()
{
    int n;
    while(cin>>n)
    {
        int ans=test.getNumber(n);
        cout<<ans<<endl;
    }
}
///<%:testing-code%>
//Powered by [KawigiEdit] 2.0!


你可能感兴趣的:(dp,ACM,DFS,tc,SRM)