题意: 给你一个数n(n<10^51),让你把他的各位数字重拍列以下,然后比他小,求方案数
非常简单的数位DP 主要是看一下代码高亮的情况
//coder : davidwang #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <ctime> #include <vector> #include <deque> #include <queue> using namespace std; #define LL long long #define X first #define Y second inline int read() { int ret=0,f=1; char ch; for (ch=getchar();ch<'0' || ch>'9';ch=getchar()) if (ch=='-') f=-f; for (;'0'<=ch && ch<='9';ch=getchar()) ret=ret*10+ch-'0'; return ret*f; } const int N = 60; LL ans,c[N][N],num[N]; char s[N]; inline LL calc(int x){ LL ret=1; for (int i=0;i<=9;i++) ret*=c[x][num[i]],x-=num[i]; return ret; } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif scanf("%s",s+1); int n=strlen(s+1); for (int i=1;i<=n;i++) num[s[i]-'0']++; c[0][0]=1; for (int i=1;i<=n;i++){ c[i][0]=1; for (int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; } for (int i=1;i<=n;i++){ for (int j=0;j<s[i]-'0';j++){ if (!num[j]) continue; num[j]--; ans+=calc(n-i); num[j]++; } num[s[i]-'0']--; } printf("%lld\n",ans); return 0; }