首页 > 编程语言 >2023牛客寒假算法基础集训营1题解

2023牛客寒假算法基础集训营1题解

时间:2023-01-17 20:11:20浏览次数:44  
标签:return re int 题解 ll long 牛客 集训营 mod

写在前面

全文收集了部分学长以及我自己的代码,本蒟蒻第一次写博客,效果不好请见谅TwT
原题链接:https://ac.nowcoder.com/acm/contest/46800#question

A:World Final? World Cup! (I)

模拟,没啥讲的啦

B:World Final? World Cup! (II)

题目大意:n<=40场球赛,甲队总共进球数为x,乙队总共进球数为y,x,y<=120,对于每场球赛胜者加3分,败者不加分,平局两队各加1分。求这n轮有多少种不同的比赛结果使得本赛季某队获得至少m<=120分。之中对于两种比赛结果,若nn轮比赛中至少有一场的比分不一样,就认为两种比赛结果不同。

  1. Scarlett的小屁孩的数学写法
    组合数学,不会的补习去https://oi-wiki.org/math/combinatorics/combination/ 看前面一部分就行了,后面的我也不会。
    image
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=998244353;
ll fac[1000],inv[1000];
ll powmod(ll a,ll b) {
  ll re=1;
  while(b) {
  	if(b&1) re=re*a%mod;
  	b>>=1;
  	a=a*a%mod;
  }
  return re;
}
ll C(int n,int m) {
  if(n<0) return 0;
  if(m<0) return 0;
  if(m>n) return 0;
  return p[n]*inv[n-m]%mod*inv[m]%mod;
}
int main() {
  fac[0]=1;
  for(int i=1; i<=200; i++) {//求阶乘 
  	fac[i]=fac[i-1]*i%mod;
  }
  inv[200]=powmod(inv[200],mod-2);
  for(int i=199; i>=0; i--) {//因为组合数涉及除法,求一下各阶乘的逆元 
  	inv[i]=inv[i+1]*(i+1)%mod;
  }
  int n,m,x,y;
  scanf("%d%d%d%d",&n,&m,&x,&y);
  ll ans=0;
  for(int a=0; a<=x; a++) {//枚举甲队的净赢球数 
  	int b=y+a-x;//已队的净赢球数 
  	if(b<0) continue;
  	for(int i=0; i<=n; i++) { //i 表示赢几场
  		for(int j=n-i; j>=0; j--) { // j 表示输几场
  			int k=n-i-j;// k 表示平几场
  			if(i*3+k<m) continue;
  			if(i==0&&a>0) continue;
  			if(j==0&&b>0) continue;
  			if(a==0&&i>0) continue;
  			if(b==0&&j>0) continue;
  			if(i>a||j>b) continue;
  			ll re=C(n,i)*C(n-i,j)%mod*C(n+x-a-1,n-1)%mod;
  			if((j==0&&b==0)&&(i==0&&a==0)) re=re%mod ;
  			else if(j==0&&b==0) re=re*C(a-1,i-1)%mod;
  			else if(i==0&&a==0) re=re*C(b-1,j-1)%mod;
  			else re=re*C(a-1,i-1)%mod*C(b-1,j-1)%mod;
  			ans=(ans+re)%mod;
  		}
  	}
  }
  printf("%lld\n",ans);
  return 0;
}
  1. 牛哇哇哇哇的dp写法
    我还没完全看懂,先贴出来,待我吃透了再更新
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int dp[2][130][105][105];
int tag[4][2][125][105][105];
void add(int &a,int b) {
  a+=b;
  if(a>=mod)a-=mod;
}
void del(int &a,int b) {
  a-=b;
  if(a<=0)a+=mod;
}
int mul(int a,int b) {
  return 1ll*a*b%mod;
}
int calc(int id,int now,int x,int y,int z) {
  if(x<0||y<0||z<0|z>100)return 0;
  return tag[id][now][x][y][z];
}
int main() {
  int n,m,x,y;
  scanf("%d%d%d%d",&n,&m,&x,&y);
  for(int _t=0; _t<=n; _t++) {
  	int now=(_t&1),nxt=1-now;
  	memset(dp[now],0,sizeof(dp[now]));
  	memset(tag[1][nxt],0,sizeof(tag[1][nxt]));
  	memset(tag[2][nxt],0,sizeof(tag[2][nxt]));
  	memset(tag[3][nxt],0,sizeof(tag[3][nxt]));
  	if(_t==0)dp[now][0][0][0]=1;
  	for(int i=0; i<=(_t+1)*3; i++) {
  		for(int j=0; j<=x; j++) {
  			for(int k=0; k<=y; k++) {
  				add(dp[now][i][j][k],calc(1,now,i,j,k-1));
  				add(dp[now][i][j][k],calc(2,now,i-3,j-1,k));
  				add(dp[now][i][j][k],calc(3,now,i-1,j,k));
  			}
  		}
  		for(int j=0; j<=x; j++) {
  			for(int k=0; k<=y; k++) {
  				add(tag[3][nxt][i][j][k],dp[now][i][j][k]);
  				add(tag[3][nxt][i][j][k],calc(3,nxt,i,j-1,k-1));

  				add(tag[1][nxt][i][j][k],dp[now][i][j][k]);
  				add(tag[1][nxt][i][j][k],calc(1,nxt,i,j,k-1));
  				add(tag[1][nxt][i][j][k],calc(1,nxt,i,j-1,k-1));
  				del(tag[1][nxt][i][j][k],calc(1,nxt,i,j-1,k-2));

  				add(tag[2][nxt][i][j][k],dp[now][i][j][k]);
  				add(tag[2][nxt][i][j][k],calc(2,nxt,i,j-1,k));
  				add(tag[2][nxt][i][j][k],calc(2,nxt,i,j-1,k-1));
  				del(tag[2][nxt][i][j][k],calc(2,nxt,i,j-2,k-1));
  			}
  		}
  	}
  }
  int ans=0;
  for(int i=m; i<=120; i++) {
  	int now=(n&1);
  	add(ans,dp[now][i][x][y]);
  }
  printf("%d",ans);
  return 0;
}

C: 现在是,学术时间 (I)

懒得写

D: 现在是,学术时间 (II)

题目大意:给出一个由平面上两点(0,0),(x,y)所确定的一个矩形A和一个点P(xp,yp)。请你求出在所有以P点作为其中一个顶点且边都平行于坐标轴的矩形B中,交集面积/并集面积的值最大为多少。
分类讨论点P相对于(x,y)的位置,写出值的表达式并分析未给出点在矩形A的哪个顶点时值最大。
注意取绝对值用fabs()

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
double x,y,xp,yp;
double s,sp;
int main(){
	int T;
	cin>>T;
	while(T--){
		cin>>x>>y>>xp>>yp;
		double s0=x*y,s1=xp*yp,s2=xp*fabs(y-yp),s3=yp*fabs(x-xp),s4=fabs(x-xp)*fabs(y-yp);
		if(xp<=x){
			if(yp<=y){
				double ans=max(s1,s2);
				ans=max(ans,max(s3,s4));
				ans=ans/s0;
				printf("%.9lf\n",ans);
			}else{
				double a=max(xp,x-xp),b=yp-y;
				double ans=a*y/(s0+a*b);
				printf("%.9lf\n",ans);
			}
		}else{
			if(yp<=y){
				double a=max(yp,y-yp),b=xp-x;
				double ans=a*x/(s0+a*b);
				printf("%.9lf\n",ans);
			}else{
				double ans=s0/s1;
				printf("%.9lf\n",ans);
			}
		}
	}
}

E: 鸡算几何

题目大意:平面上有一个L型铁丝ABC,规定中间字母为L的拐角。给出原先ABC以及变化后DEF各点坐标,问ABC能否只通过平面上的平移旋转得到DEF?
可以先在纸上写个L自己模拟转一下,可以发现如果以长边竖直,拐角在下的视角看去,短边永远在左侧或永远在右侧。
于是可以通过鞋带定理,以长边端点-拐角-短边端点的顺序求值,如果顺序为顺时针值为负,逆时针为正。
而两边等长分不出长短边,也无法判断是否进行过三维变换。
注意:浮点比较不能用==,判断差值的绝对值是否小于误差就行了

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
struct node{
	double x,y;
}poi[10];
inline double dis(int i,int j){
	node x=poi[i],y=poi[j];
	return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}
double Exp=0.000000001;
int main(){
	int T;
	cin>>T;
	while(T--){
		for(int i=1;i<=6;i++){
			cin>>poi[i].x>>poi[i].y;
		}
		double lenmx=dis(1,2),lenmn=dis(2,3);
		int mx=1;
		if(lenmx<lenmn) swap(poi[1],poi[3]);
		if(fabs(lenmx-lenmn)<Exp){
			cout<<"NO\n";
			continue;
		}
		double slenmx=dis(4,5),slenmn=dis(5,6);
		int smx=4;
		if(slenmx<slenmn) swap(poi[4],poi[6]);
		double ans1=0,ans2=0;
		for(int i=1;i<=3;i++) ans1+=poi[i].x*(poi[(i==3?1:i+1)].y-poi[(i==1?3:i-1)].y);
		for(int i=4;i<=6;i++) ans2+=poi[i].x*(poi[(i==6?4:i+1)].y-poi[(i==4?6:i-1)].y);
		if((ans1<0&&ans2<0)||(ans1>0&&ans2>0)) cout<<"NO\n";
		else cout<<"YES\n";
	}
}

F: 鸡玩炸蛋人

题目大意就懒写了,反正看的都是集训队的
简单并查集

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m;
ll a[100100],fa[100100],sum[100100];
inline int find(int x){
	if(fa[x]==x)return x;
	else return fa[x]=find(fa[x]);
}
inline void merge(int x,int y){//sum记录每个集的节点数
	x=find(x),y=find(y);
	if(x==y) return;
	fa[x]=y;
	sum[y]+=sum[x];
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		fa[i]=i;
		sum[i]=1;
	}
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		merge(u,v);
	}
	int fl=1,k=0;//明显只有炸弹都在同一集内才有可能放置
    //fl为1表示所有节点都没放
    //2表示炸弹在不同集
    //0表示炸弹在同一集
    //k纪律炸弹在以谁为祖先的集内
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]){
			if(fl==1) fl=0;
			int g=find(i);
			if(k==0) k=g;
			if(k!=g) fl=2;
		}
	}
    //可以发现在一个集内,每个节点都可以成为S或T,故方案数为集节点数的平方
    //我不太会描述,可以手动模拟一下,类似于图的遍历,你可以回溯的时候再放炸弹,所以不用担心炸弹挡路
	if(fl==2) cout<<0;
	else if(fl==1){
		ll ans=0;
		for(int i=1;i<=n;i++) if(fa[i]==i){
			ans+=sum[i]*sum[i];
		}
		cout<<ans;
	}else{
		cout<<sum[k]*sum[k];
	}
}

G: 鸡格线

1.线段树维护,暴力修改
这题写过基本一样的啊,可惜我最后5分钟才看题没时间写了
先手动模拟一下函数f(x),带入最大值1e9,发现11次后得到100,所以对于每个区间记录次数,超过11次就之间返回,我因为怕翻车就设定为13次了。
对于询问直接输出节点1的值。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls i<<1
#define rs i<<1|1
#define mid (l+r>>1)
#define endl '\n'
#define N 100100
int n,m;
ll val[N<<2],lz[N<<2];

inline void pu(int i){
	val[i]=val[ls]+val[rs];
}
inline void build(int i,int l,int r){
	val[i]=lz[i]=0;
	if(l==r){
		scanf("%lld",&val[i]);
		return ;
	}
	build(ls,l,mid),build(rs,mid+1,r);
	pu(i);
}
inline void upd(int i,int l,int r,int x,int y,int k){
	if(x<=l&&r<=y){
		if(lz[i]>=13) return;
		else lz[i]+=k;
	}
	if(l==r){
		for(int j=1;j<=k;j++){
			val[i]=(int)(10.0*sqrt(val[i])+0.5);
		}
		return ;
	}
	if(x<=mid) upd(ls,l,mid,x,y,k);
	if(mid<y) upd(rs,mid+1,r,x,y,k);
	pu(i);
}
int main(){
	scanf("%d%d",&n,&m);
	build(1,1,n);
	int op,x,y,k;
	while(m--){
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d%d",&x,&y,&k);
			k=min(13,k);
			if(k)upd(1,1,n,x,y,k);
		}else{
			printf("%lld\n",val[1]);
		}
	}
}

2.STL

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main(){
    int T = 1;
    while(T--){
        int n,m;
        cin>>n>>m;
        LL sum = 0;
        map<int,int> a;
        for(int i=1;i<=n;i++){
            int x;
            cin>>x;
            a[i] = x;
            sum += x;
        }
        a[n+1] = 1;
        a[-1] = 1;
        while(m--){
            int t;
            cin>>t;
            if(t==2) cout<<sum<<endl;
            else{
                int l,r,k;
                cin>>l>>r>>k;
                for(auto it=a.lower_bound(l);it->first<=r;it++){
                    auto &[i,y] = *it;
                    for(int j=1;j<=k;j++){
                        int x = round(sqrt(y)*10);
                        sum -= y;
                        sum += x;
                        if(x==y){
                            it = a.erase(it);
                            it--;
                            break;
                        }
                        y = x;
                    }
                }
            }
        }
    }
    return 0;
}

H: 本题主要考察了DFS

我信了他的鬼话,dfs写了半天。。。
“这H 我愿称其为质量守恒”

#include<bits/stdc++.h>
using namespace std;
int n,T,cnt;
int main(){
	cin>>T;
	while(T--){
		cin>>n;
		cnt=n*n-1;
		int p=10;
		for(int i=1;i<=cnt;i++){
			string s;
			cin>>s;
			for(int j=0;j<4;j++){
				if(s[j]=='1') p++;
				else if(s[j]=='2') p--;
			}
		}
		cout<<p<<endl;
	}
}

I: 本题也主要考察了DFS

注意:牛牛点最多只要一个!!!
Scarlett的小屁孩的代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const int mod = 998244353;
const int N = 1e5 + 10;
int a[110][110];
bool vis[110][110];//是否为牛牛点 
bool used[10010];//当前数字是否被用过 
int n, m, t;
void No() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			printf("0%c", j == n ? '\n' : ' ');
		}
	}
}
void Print() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			printf("%d%c", a[i][j], j == n ? '\n' : ' ');
		}
	}
}
bool check(int x, int y) {
	int Max = 0, Min = 1e9;
	for (int i = 1; i <= n; i++) {
		Max = max(Max, a[x][i]);
		Min = min(Min, a[i][y]);
	}
	if (Max != a[x][y] || Min != a[x][y])return 0;
	return 1;
}
void solve() {
	memset(used, 0, sizeof used);
	memset(a, 0, sizeof a);
	memset(vis, 0, sizeof vis);
	scanf("%d%d",&n,&m);
	for (int i = 1,op,x,y,k; i <= m; i++) {
		scanf("%d%d%d",&op,&x,&y);
		if (op == 1) {
			scanf("%d",&k);
			a[x][y] = k;
			used[k] = 1;
		} else {
			vis[x][y] = 1;
		}
	}
	int cnt = 0;//统计牛牛点数量 
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cnt += vis[i][j];
		}
	}
	if (cnt > 1) {//大于一个打印0矩阵 
		No();
		return;
	}else if (cnt == 0) {//没有牛牛点 
		int P = 1;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (a[i][j]) continue;
				while (used[P]) P++;//如果这个数字被用过之间跳过 
				used[P] = 1;
				a[i][j] = P;
			}
		}
		Print();
	} else if (cnt == 1) {
		int L = 1, R = n * n;//上下界 
		int x, y;//记录牛牛点的坐标 
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (vis[i][j]) {
					x = i, y = j;
					break;
				}
			}
		}
		for (int i = 1; i <= n; i++) {//遍历牛牛点所在列 
			if (i == x) continue;//先跳过牛牛点,因为它只能是列中最小的 
			if (a[i][y]) continue;//赋过值就跳过 
			while (used[R]) R--;//尽量放大的 
			if (R <= 0) {//如果没数可放说明失败了 
				No();
				return;
			}
			used[R] = 1;
			a[i][y] = R;
		}
		for (int i = 1; i <= n; i++) {
			//因为牛点只能是列内最小的,但之前因为要尽量放大数所以直接跳过了已赋值点
			//现在出了牛点都要遍历,更新R为列内除牛点外最小值-1,即牛点值的上界 
			if (i == x) continue;
			R = min(R, a[i][y] - 1);
		}
		while (used[R])R--;//但是R可能被用过了,还需要更新一次,现在R是真正的牛点值的上界 
		for (int i = 1; i <= n; i++) {//现在遍历牛点所在行,原理同上 
			if (i == y) continue;
			if (a[x][i]) continue;
			while (used[L]) L++;
			if (L > n * n) {
				No();
				return;
			}
			used[L] = 1;
			a[x][i] = L;
		}
		for (int i = 1; i <= n; i++) {
			if (i == y) continue;
			L = max(L, a[x][i] + 1);
		}
		while (used[L])L++;
		if (!a[x][y] && L <= R) {//如果牛点没赋值且上下界内可以取值 
			a[x][y] = L;
			used[L] = 1;
		} else if (!a[x][y]) {//如果牛点没赋值且上下界内不可以取值
			No();
			return;
		}
		int P = 1;
		for (int i = 1; i <= n; i++) {//填数 
			for (int j = 1; j <= n; j++) {
				if (a[i][j]) continue;
				while (used[P]) P++;
				used[P] = 1;
				a[i][j] = P;
			}
		}
		//注意!之前遍历牛点所在行列时遇到已赋值的点是直接跳过去的
		//现在要检查赋的值是否合理了 
		if (check(x, y)) Print();
		else No();
	}
}
int main() {
	scanf("%d",&t);
	while (t--)
		solve();
	return 0;
}

J: 本题竟也主要考察了DFS

Scarlett的小屁孩的代码
极其恼人的分类讨论,我逻辑还没彻底理清,先留一坑

#include<bits/stdc++.h>
using namespace std;
int a,b,c,t;
void solve() {
	scanf("%d%d%d",&a,&b,&c);
	if (a == 0) {
		printf("1\n");
		return;
	}
	if ((a & c) != c) {
		printf("1\n");
		return;
	}
	if (b == 0) {
		printf("2\n");
		return;
	}
	if (b != c && c != 0) {
		printf("2\n");
		return;
	}
	if (b == c) {
		printf("2\n");
		return;
	}
	printf("-1\n");
}
int main() {
	cin>>t;
	while (t--)
		solve();
	return 0;
}

K: 本题主要考察了dp

可以发现1001001001...可以在使用0数量最少的情况下让坏串最少

#include<bits/stdc++.h>
using namespace std;
int n,m,c;
int a[1100];
int cnt=0;
int main() {
	cin>>n>>m;
	c=n-m;//0的数量
	for(int i=1,j=0; i<=n; i++,j--) {
		if(j==0) {//当j为0时说明现在可以放1了
			if(m) {//如果1有剩余
				m--;
				a[i]=1;
				j=3;
			} else {//如果1用完了
				c--;
				a[i]=0;
			}
		} else {//现在不适合放1
			if(c){//如果0有剩余
				c--;
				a[i]=0;
			}else{//0用完了只能放1了
				m--;
				a[i]=1;
			}
		}
	}
	for(int i=1;i<=n-2;i++){//放完后直接统计坏串数
		int cnt0=0,cnt1=0;
		for(int j=i;j<=i+2;j++){
			if(a[j]) cnt1++;
			else cnt0++;
		}
		if(cnt1>cnt0) cnt++;
	}
	cout<<cnt;
}

L: 本题主要考察了运气

高中概率

M: 本题主要考察了找规律

牛哇哇哇哇的代码
“看到题目不考虑dp就不算入门”

#include<bits/stdc++.h>
using namespace std;
int n,m;
double dp[550][550];//1~i个朋友分完了j个先辈的好感动和 

int main(){
	cin>>n>>m;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=m;j++){
			dp[i][j]=-1e18;//不要用memset赋值,否则结果很奇怪 
		}
	}
	dp[0][0]=0;
	for(int i=0;i<n;i++){//枚举朋友,因为转移给i+1,所以[0,n-1] 
		for(int j=0;j<=m;j++){
			dp[i+1][j]=max(dp[i+1][j],dp[i][j]);//如果不给第i+1个朋友先辈 
			for(int k=1;k<=m-j;k++){//枚举要给i+1个朋友多少个 
				dp[i+1][j+k]=max(dp[i+1][j+k],dp[i][j]+1.0*k/(m-j));
			}
		}
	}
	double ans=dp[n][m];
	printf("%.9lf",ans);
}

总结

严重的标题欺骗!不应该死磕某道题或者某种算法。

标签:return,re,int,题解,ll,long,牛客,集训营,mod
From: https://www.cnblogs.com/EndPB/p/17058166.html

相关文章

  • 洛谷普及组模拟赛 题解报告
    洛谷普及组模拟赛题解报告\[\bf{Prepared\by\InoueTakina.}\]前言:祝大家身体健康。本场比赛较为良心,经过了多次难度平衡,应该严格低于NOIP2018提高组,相信大家......
  • 洛谷P3195 玩具装箱 题解报告
    题目地址题意:如题所述。分析:斜率优化dp模板题。题目没看清就下手,自以为题面所述中i>j;原始dp式子也没设计准确。中途在错误方向上头铁时,甚至没注意到横坐标是沿......
  • 洛谷P3628 特别行动队 题解报告
    题目地址题意:把正整数序列分隔为若干区间,若单个区间的元素之和为X,则其贡献为\(aX^2+bX+c\)。求所有区间的贡献之和的最大值。分析:斜率优化dp模板题。这篇博客描述得......
  • 2023牛客寒假训练营1补题
    K分析思维题,先考虑100100100....这样一个序列能接受最多的1的情况如果有多的1,就先从后面开始放赛时是一样的思路,但是细节方面没处理好代码#include<bits/stdc++.h>u......
  • 【2023牛客寒假算法基础集训营1】小复盘
    AWorldFinal?WorldCup!(I)4种情况,想全就过。A先踢numaA当前踢进的数量numbB当前踢进的数量①A踢完/A必赢/B还能踢k脚numa>numb+k②A踢完/B必赢/A还能踢k脚nu......
  • 1.17模拟赛题解
    T1设\(dp_{i,j}\)前\(i+j\)个人站队,第一排站\(i\)个人的方案数。每次对相同身高的一段人进行转移。暴力复杂度是正确的。时间复杂度\(O(n^2)\)。T4考虑二分答......
  • iSCSI的客户端messages频繁报错问题解决
    问题现象:在自己的工作站中安装的RAC测试环境,使用了iSCSI模拟共享存储,环境运行OK,但是在messages信息中频繁报错如下:[root@db01rac2~]#tail-20f/var/log/messagesJan......
  • 送礼物题解
    题目描述达达帮翰翰给女生送礼物,翰翰一共准备了N个礼物,其中第i个礼物的重量是G[i]。达达的力气很大,他一次可以搬动重量之和不超过W的任意多个物品。达达希望一次搬......
  • 清单计价-2022鹏业云计价i20常见问题解答整理
    1、如何批量将EXCEL报表的工程结构、清单和定额一次性导入计价软件?答:通过云计价i20软件的“导入Excel新建”功能,可以将招标控制价、投标报价等多种类型的表格一次性导入软件......
  • CF1748B题解
    题目传送门简要题意给定一个长度为\(n\)的只由数字\(0\)到\(9\)组成的字符串\(s\),求\(s\)中有多少个子串满足所有数字出现次数的最大值小于等于出现的不同数......