[ABC201]Secret Number
壹、题目描述 ¶
中文描述:
一个 \(\rm PIN\) 由四位数字组成,可以包含重复的数字;
给你一个长度为 \(10\) 的字符串,下标从 \(0\) 开始。对于 \(s_i\),它的含义如下:
- 若 \(s_i=\tt{o}\),则要求构造的 \(\rm PIN\) 必须有数字 \(i\);
- 若 \(s_i=\tt{x}\),则要求构造的 \(\rm PIN\) 必须没有数字 \(i\);
- 若 \(s_i=\tt{?}\),则要求构造的 \(\rm PIN\) 不一定要包含数字 \(i\);
对于给定的字符串,有多少种不同的 \(\rm PIN\) 码?
数据范围:\(|S|=10,s_i\in\{\tt{o,x,?}\}\).
贰、题解 ¶
只有 \(4\) 位!只有 \(10\) 个字符!那么我们可以直接上 \(\mathcal O(10^4)\) 或者 \(\mathcal O(10^4\times 10)\) 的算法了。
加强版试题:
一个 \(\rm NIP\) 由 \(n\) 个颜色组成,可以包含重复的颜色;
给你一个长度为 \(m\) 的字符串,下标从 \(0\) 开始。对于 \(s_i\),它的含义如下:
- 若 \(s_i=\tt{o}\),则要求构造的 \(\rm NIP\) 必须有颜色 \(i\);
- 若 \(s_i=\tt{x}\),则要求构造的 \(\rm NIP\) 必须没有颜色 \(i\);
- 若 \(s_i=\tt{?}\),则要求构造的 \(\rm NIP\) 不一定要包含颜色 \(i\);
对于给定的字符串,有多少种不同的 \(\rm NIP\) 码?答案对 \(998244353\) 取模。
数据范围:\(m\le 10^6,n\le 10^9\).
我们可以使用容斥!具体容斥有多少个没有填的必填颜色数量,记 \(k\) 为必填颜色种数,\(p\) 为可以填的颜色(即必填、不一定都算在里面),那么我们就有容斥的式子:
\[\sum_{i=0}^k(-1)^i{k\choose i}\times (p-i)^n
\]
时间复杂度 \(\mathcal O(m\log n)\).
叁、参考代码 ¶
时间复杂度 \(\mathcal O(10^4)\).
char s[maxn+5];
int vis[maxn+5], cnt;
int ans=0;
void dfs(int u, int now){
if(u==5){
if(now==cnt) ++ans;
return;
}
rep(i, 0, 9) if(s[i]!='x'){
if(!vis[i] && s[i]=='o') ++now;
++vis[i];
dfs(u+1, now);
if((--vis[i])==0){
if(s[i]=='o') --now;
}
}
}
signed main(){
scanf("%s", s);
rep(i, 0, 9) if(s[i]=='o')
++cnt;
if(cnt>4) return printf("0\n"), 0;
dfs(1, 0);
printf("%d\n", ans);
return 0;
}
时间复杂度 \(\mathcal O(m\log n)\)(请忽略 \(\tt mypow\) 的复杂度,把他当成 \(\log\) 的快速幂吧)
#define int long long
const int maxn=10;
const int maxc=10;
char s[maxn+5];
int C[maxc+5][maxc+5], fac[maxc+5];
int cnto, cnt;
inline void init(){
fac[0]=1;
rep(i, 1, maxc) fac[i]=fac[i-1]*i;
rep(i, 0, maxc){
C[i][0]=C[i][i]=1;
rep(j, 1, i-1)
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
inline int mypow(int a, int n){
int ret=1;
rep(i, 1, n) ret*=a;
return ret;
}
signed main(){
init();
scanf("%s", s);
rep(i, 0, 9){
cnto+=(s[i]=='o');
cnt+=(s[i]=='o' || s[i]=='?');
}
int ans=0;
rep(i, 0, cnto){
ans=ans+C[cnto][i]*((i&1)? -1: 1)*mypow(cnt-i, 4);
}
printf("%lld\n", ans);
return 0;
}