[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=2425
[算法]
类似与数位动态规划的思想 , 用组合数学进行简单推导即可
时间复杂度 : O(L ^ 3)
[代码]
#include<bits/stdc++.h> using namespace std; #define N 110 typedef long long ll; typedef long double ld; typedef unsigned long long ull; #define int ll int L , L0; int tmp[N] , digit[N] , cnt[N]; char s[N]; template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline ll quickpow(ll a , int n) { ll b = a , res = 1; while (n > 0) { if (n & 1) res *= b; b = b * b; n >>= 1; } return res; } inline void add(int x , int val) { for (int i = 2; i <= (int)sqrt(x); i++) { if (x % i == 0) { while (x % i == 0) { tmp[i] += val; x /= i; } } } if (x > 1) tmp[x] += val; } signed main() { scanf("%s" , s + 1); L = strlen(s + 1); for (int i = 1; i <= L; i++) { if (s[i] > '0') ++L0; ++cnt[s[i] - '0']; digit[i] = s[i] - '0'; } ll ans = 0; for (int k = 1; k < L;k++) { if (k < L0) continue; memset(tmp , 0 , sizeof(tmp)); for (int i = 1; i <= L0; i++) add(i , 1); for (int i = 1; i <= 9; i++) { for (int j = 1; j <= cnt[i]; j++) { add(j , -1); } } for (int i = 1; i <= k - 1; i++) add(i , 1); for (int i = 1; i <= L0 - 1; i++) add(i , -1); for (int i = 1; i <= k - L0; i++) add(i , -1); ll cont = 1; for (int i = 1; i <= 100; i++) cont *= quickpow(i , tmp[i]); ans += cont; } for (int i = 1; i <= L; i++) { for (int j = 0; j < digit[i]; j++) { if (i == 1 && !j) continue; if (!j || cnt[j] > 0) { --cnt[j]; int nowcnt = 0; for (int k = 1; k <= 9; k++) nowcnt += cnt[k]; if (nowcnt > L - i) { ++cnt[j]; continue; } memset(tmp , 0 , sizeof(tmp)); for (int k = 1; k <= nowcnt; k++) add(k , 1); for (int x = 1; x <= 9; x++) { for (int y = 1; y <= cnt[x]; y++) { add(y , -1); } } for (int k = 1; k <= L - i; k++) add(k , 1); for (int k = 1; k <= nowcnt; k++) add(k , -1); for (int k = 1; k <= L - i - nowcnt; k++) add(k , -1); ll cont = 1; for (int k = 1; k <= 100; k++) cont *= quickpow(k , tmp[k]); ans += cont; ++cnt[j]; } } --cnt[digit[i]]; } printf("%lld " , ans); return 0; }