P2518 [HAOI2010]计数 类似数位dp

题意

你有一组非零数字(不一定唯一),你可以在其中插入任意个0,这样就可以产生无限个数。比如说给定{1,2},那么可以生成数字12,21,102,120,201,210,1002,1020,等等。

现在给定一个数,问在这个数之前有多少个数。(注意这个数不会有前导0).

思路

注意题目的数据不一定只有1,或者2,而是看输入有多少数字。

其实可以转化为,有多少个全排列小于给定的数字,因为把0去掉相当于把0拿到前面去。
具体写的时候,类似数位dp的思路。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert> /* ⊂_ヽ
  \\ Λ_Λ 来了老弟
   \('ㅅ')
    > ⌒ヽ
   /   へ\
   /  / \\
   レ ノ   ヽ_つ
  / /
  / /|
 ( (ヽ
 | |、\
 | 丿 \ ⌒)
 | |  ) /
'ノ )  Lノ */ using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n' #define boost ios::sync_with_stdio(false);cin.tie(0)
#define rep(a, b, c) for(int a = (b); a <= (c); ++ a)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c); const ll oo = 1ll<<;
const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //
const int mod = 1e9;
const double esp = 1e-;
const double PI=acos(-1.0);
const double PHI=0.61803399; //黄金分割点
const double tPHI=0.38196601; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} inline void cmax(int &x,int y){if(x<y)x=y;}
inline void cmax(ll &x,ll y){if(x<y)x=y;}
inline void cmin(int &x,int y){if(x>y)x=y;}
inline void cmin(ll &x,ll y){if(x>y)x=y;} /*-----------------------showtime----------------------*/
const int maxn = ;
char str[maxn];
int cnt[],val[maxn];
ll dp[maxn][maxn];
ll C(int n, int m) {
if(m < || n < || n < m) return ;
if(dp[n][m]) return dp[n][m];
if(n == m || m == ) return ;
return dp[n][m] = C(n-, m) + C(n-, m-);
} ll cal(int n){
ll res = ;
for(int i=; i<=; i++)
if(cnt[i] > )
res *= C(n, cnt[i]), n-= cnt[i];
return res;
}
int main(){
// debug(C(4, 2));
scanf("%s", str);
int len = strlen(str);
for(int i=; i<len; i++) {
val[i+] = str[i] - '';
cnt[str[i] - ''] ++;
}
ll ans = ,n = len; for(int i=; i<=len; i++) {
n--;
for(int j=; j<val[i]; j++) {
cnt[j]--;
ans += cal(n);
cnt[j]++;
}
cnt[val[i]]--;
}
printf("%lld\n", ans);
return ;
}
上一篇:socket,TCP/IP的理解


下一篇:JavaScript随机生成颜色以及十六进制颜色 与RGB颜色值的相互转换