蒟蒻的补档题(长期更新)

补档

长期更新……这里是我做过并且感觉有收获的题


小仙女过生日啦

看了题解,是“区间dp经典例题——“凸多边形的三角剖分””……但是还没懂

知识点

1.叉积求三角形面积

之前自己只会个海伦公式……

找这个的时候我还看到了行列式,是线代里的,自己本来是打算寒假学的,结果净去过写题了……

double S(point a,point b,point c){
    //注意这里相减的顺序不能变
	return fabs((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x))/2;
}

2.判断一个点是否在三角形内

bool judge(point a,point b,point c){
	double s1=S(a,b,c);
	rep(i,1,n){
		int x=p[i].x,y=p[i].y;
		if(x==a.x&&y==a.y||x==b.x&&y==b.y||x==c.x&&y==c.y){
			continue;
		}
		double s2=S(a,b,p[i])+S(a,c,p[i])+S(b,c,p[i]);
        //因为是浮点数,所以不能直接相等
		if(fabs(s1-s2)<=1e-8) return false;
	}
	return true;
}

代码

蒟蒻只会dp的板子,这主函数部分就看不懂了……

const int N=1e2+5;
double f[N][N];
int n;
struct point{
	double x,y;
}p[N];
double S(point a,point b,point c){
	return fabs((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x))/2;
}
bool judge(point a,point b,point c){
	double s1=S(a,b,c);
	rep(i,1,n){
		int x=p[i].x,y=p[i].y;
		if(x==a.x&&y==a.y||x==b.x&&y==b.y||x==c.x&&y==c.y){
			continue;
		}
		double s2=S(a,b,p[i])+S(a,c,p[i])+S(b,c,p[i]);
		if(fabs(s1-s2)<=1e-6) return false;
	}
	return true;
}
signed main()
{
//std::ios::sync_with_stdio(false);
//cin.tie(0);
//cout.tie(0);
	while(cin>>n){
		rep(i,1,n) cin>>p[i].x>>p[i].y;
		rep(i,1,n-2){
			f[i][i+2]=S(p[i],p[i+1],p[i+2]);
		}
		rep(len,4,n){
			rep(i,1,n-len+1){
				int j=i+len-1;
				f[i][j]=0x3f3f3f3f;
				rep(k,i+1,j-1){
					if(judge(p[i],p[k],p[j])){
						f[i][j]=min(f[i][j],max(S(p[i],p[k],p[j]),max(f[i][k],f[k][j])));
					}
				}
			}
		}
		cout<<fixed<<setprecision(1)<<f[1][n]<<endl;		
	}

	return 0;
}


Forsaken喜欢数论

求前n个数的最小质因子的和。

在从 1 到 n遍历整数时,使用筛法求素数。
如果本身是素数,那么它本身就是它的最小质因子,累加计入 ans。
遍历由该素数生成的合数,如果还没访问过,表示这个合数的最小质因子就是该素数,累加计入ans。——Forsaken喜欢数论_牛客博客

	int n,ans=0;cin>>n;
	vector<bool>v(n+1,0);
	for(int i=2;i<=n;i++){
		if(!v[i]){
			ans+=i;
			for(int j=i*i;j<=n;j+=i){
				if(!v[j]){
					v[j]=1;
					ans+=i;
				}
			}
		}
	} 
	cout<<ans;
	return 0;


字符串

双指针

先找到一个从0开始包含所有小写字母的最短长度,并统计每个小写出现多少次,然后右指针移位,相应的字符统计++,然后对与左指针进行移位,移位到不能移位为止,即两指针中间出现有些字符不存在为止 ——字符串_牛客博客

const int N=27;
int v[N];
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
	string s;cin>>s;
	int sum=0,r=-1,ans=1e9,len=s.length();
	for(int l=0;l<len;l++){
		while(sum<26){
			r++;
			if(r>len-1) break;		
			if(!v[s[r]-'a']) sum++;							
			v[s[r]-'a']++;						
		}
		if(v[s[l]-'a']==1) sum--;
		v[s[l]-'a']--;
		if(sum==26) ans=min(ans,r-l);
	}
	cout<<ans;
	return 0;
}

小红勇闯地下城

最短路 迪杰斯特拉

因为读入权值的问题卡了两小时(⊙﹏⊙)

要注意的点

学了果然完全不等于会了-^-

const int N=1e5+5;
int dis[N],v[N];
vector<pair<int,int>>g[N];
string s[N];
int op[4][2]={1,0,-1,0,0,1,0,-1};
//这种写法:op[0][0]=1,op[0][1]=0,op[1][0]=-1,op[1][1]=0
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
	int q;cin>>q;
	while(q--){
		int n,m,h;cin>>n>>m>>h;	
        //不能从s[1]开始输入,所以此次只能从0开始
		rep(i,0,n-1) cin>>s[i];
		int sx=0,sy=0,ex=0,ey=0;
		rep(i,0,n-1){
			rep(j,0,m-1){
				dis[i*m+j]=1e9;
                v[i*m+j]=0;
				g[i*m+j].clear();
                //当时这里给写下面一个循环去了
				if(s[i][j]=='T') ex=i,ey=j,s[i][j]='0';
				else if(s[i][j]=='S') sx=i,sy=j,s[i][j]='0';
			}
		}
		rep(i,0,n-1){
			rep(j,0,m-1){
				rep(k,0,3){
                    //注意nx与i的对应
					int nx=i+op[k][0],ny=j+op[k][1];
					if(nx<0||ny<0||nx==n||ny==m) continue;
					g[i*m+j].push_back({nx*m+ny,s[nx][ny]-'0'});
				}
			}
		}
		priority_queue<pair<int,int>>qq;
		dis[sx*m+sy]=0;
		qq.push({0,sx*m+sy});
        //此题可以不用判重
		while(!qq.empty()){
			auto t=qq.top();
			qq.pop();
			int u=t.second;
            //if(v[u]) continue;
            //v[u]=1;
			for(auto ed:g[u]){
				int v=ed.first,w=ed.second;
				if(dis[v]>dis[u]+w){
					dis[v]=dis[u]+w;
					qq.push({-dis[u],v});
				}
			}
		}
		if(dis[ex*m+ey]<h) cout<<"Yes";
		else cout<<"No";
		cout<<endl;
	}
	return 0;
}


E-小红的树形 dp_牛周赛 Round 34

初看是图论(有建边),再看是数据结构(有建树),现在看是二者皆有

二分图染色,还是第一次见到这个知识点的题(⊙﹏⊙)

知识点

二分图染色 实际上是一种树的应用(个人理解),父节点(可以理解为一条边的一点)与其子节点(与该点相连的另一个点)颜色相反,为了实现这种操作,需要建树加染色两步

//建树,分别是u作父节点,v作子节点;u作子节点,v作父节点
rep(i,1,n-1){
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
//染色,先把第一个节点染色为1,枚举第一个节点的子节点(它的出边)
dfs(1,0,1);
void dfs(int x,int pr,int p){//x表示当前节点编号,pr表示当前节点的上一个节点,p表示要染的颜色
	dp[x]=p;
	for(auto i:g[x]){
        //当x的子节点i等于上一个节点时,因为上一节点已染色,不继续递归
		if(i==pr) continue;
		dfs(i,x,1-p);//递归到子节点
	}
}

分析

可以把'd'看成一种颜色,'p'是另一种,'?'是未染色,输入的u,v代表给第u个节点与第v个节点染上相反的颜色,如果和已有的颜色冲突,则输出-1,否则输出染色结果

完整代码

const int N=2e5+5;
vector<int>g[N];
int dp[N];
void dfs(int x,int pr,int p){
	dp[x]=p;
	for(auto i:g[x]){
		if(i==pr) continue;
		dfs(i,x,1-p);
	}
}
void solve(){
	int n,u,v;string s;cin>>n>>s;
	s=' '+s;//移位,使字符串下标从1开始
	rep(i,1,n-1){
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,0,1);
// 	rep(i,1,n) cout<<dp[i]<<" ";
// 	cout<<endl;
	set<int>d,p;//存下d或p的位置节点的颜色种类
	for(int i=1;i<=n;i++){
		//cout<<s[i]<<" "<<dp[i]<<endl;
		if(s[i]=='d') d.insert(dp[i]);
		if(s[i]=='p') p.insert(dp[i]);
	}
	//cout<<(*d.begin())<<" "<<(*p.begin())<<endl;
    //当d或p的位置节点存到颜色超过一种,输出-1
	if(d.size()>1||p.size()>1){//不能是!=1,因为?dd? 中p.size()=0 
		cout<<-1<<endl;
		return ;
	}
    //当d,p位置颜色相同,输出-1
	else if(d.size()==1&&p.size()==1&&*d.begin()==*p.begin()){
		cout<<-1<<endl;
		return ;
	}
	if(*d.begin()==1){
		rep(i,1,n){
			if(dp[i]) cout<<"d";
			else cout<<"p";
		}
	}
	else{
		rep(i,1,n){
			if(dp[i]) cout<<"p";
			else cout<<"d";
		}
	}
}


D-小红数组操作_牛客周赛 Round 31

数组模拟链表

两个操作:

  1. 输入1 x y,将x插入在元素y的右边。保证此时数组中没有元素等于x,且数组中存在一个y。特殊的,如果将x插入在数组的最左边,则y=0
  2. 输入2 x,将元素x删除。
#include<bits/stdc++.h>
using namespace std;
map<int,int>l,r;//l[i]与r[i]分布代表第i个元素的左右节点 
int main(){
    int n,q,x,y,op;
    cin>>q;
    while(q--){
        cin>>op>>x;
        if(op==1){//将x插入y的右边 
            cin>>y;
			if(r.count(y)){
				r[x]=r[y];
				l[r[y]]=x;
			}
            l[x]=y;
            r[y]=x;
        }
        else{//将元素x删除 
            if(l.count(x)){//x有前驱 
            	if(r.count(x)) r[l[x]]=r[x];
            	else r.erase(l[x]);
            }
            if(r.count(x)){
            	if(l.count(x)) l[r[x]]=l[x];
            	else l.erase(r[x]);
            }
            l.erase(x),r.erase(x);
        }
    }
    x=0;
    vector<int>out;
    //输出整个数组 
    while(r.count(x)){
    	x=r[x];
        out.push_back(x);
    }
    cout<<out.size()<<"\n";
    for(auto i:out) cout<<i<<" ";
}

数字之和

很经典的01背包问题,但我就是一点dp方向的思路都没有,因为数据量小,也可以用每次输入遍历set来更新

解法1

因为sum(a[i])最大为10000,可以对每个a[i]枚举它的所有合法的加和值,这样就能得到所有a数组可能的权值

也就是把当前的a[i]与i以前的每a[i]相加,加和值用数组v标记下来

代码

const int N=1e4+5;
int a[N],v[N];
void solve(){
	int n,sum=0;cin>>n;
	rep(i,1,n){
		cin>>a[i];
        sum+=a[i];
	}
	v[0]=1;
	rep(i,1,n){
		per(j,sum,0){
			if(v[j]&&j+a[i]<=sum){
				v[j+a[i]]=1;
			}
		}
	}
	int ans=0; 
	rep(i,1,sum){
		if(v[i]) ans++;
	}
	cout<<ans;
}

解法2

每次输入遍历set,把加和值存进tmp里,再把tmp的元素插入set中

const int N=1e3+5;
int a[N];
set<int>s;
void solve(){
	int n,x;cin>>n;
	rep(i,1,n){
		cin>>x;
		vector<int>tmp;
		for(auto it:s){
			if(!s.count(it+x)) tmp.push_back(it+x);
		}		
		for(auto it:tmp) s.insert(it);
		s.insert(x);
	} 
	cout<<s.size();
}


解法3(最优解)

每种状态用dp存下来,dp[j]表示前i个数,组成的和为j是否可行,可行为1,不可行为0,这样答案ans=sum(dp[j]==1)。初始化dp[0]=1,转移方程:dp[j]|=dp[j-a[i]]

代码

const int N=1e4+5;
int dp[N],a[N];
void solve(){
	int n,sum=0;cin>>n;
	rep(i,1,n){
		cin>>a[i];
        sum+=a[i];
	}
	dp[0]=1;
	rep(i,1,n){
		per(j,sum,a[i]){
			dp[j]|=dp[j-a[i]];
		}
	}
	int ans=0; 
	rep(i,1,sum){
		if(dp[i]) ans++;
	}
	cout<<ans;
}

几番烟雾,只有花难护

数论分块里的向上取整

知识点&分析

详见数论分块

代码

const int M=998244353;
int fp(int b,int p){
	int res=1;
	while(p){
		if(p&1) res=res*b%M;
		b=b*b%M;
		p>>=1;
	}
	return res;
}
int s=fp(6,M-2)%M;
int f(int n){
	return((n*(n+1)%M*(n*2+1)%M)%M*s)%M;
}
void solve(){
	int n;cin>>n;
	//cout<<f(0)<<" "<<f(1)<<" "<<f(2)<<" "<<f(3)<<endl;
	int ans=0;
	for(int l=1,r,k;l<=n;l=r+1){
		k=(n+l-1)/l;
		if(k==1) r=n;
		else r=(n-1)/(k-1);
		//cout<<l<<" "<<r<<" "<<k<<endl;
		ans+=k*(f(r)-f(l-1)+M)%M;
	}
	cout<<(ans+M)%M<<endl;
}



1715-C: 秒了 -- Power OJ

考察模法的性质🐻‍❄️

分析

模法结果实际上是求余,所以我们可以模拟除法,求出最后的余数

操作

代码

int get_len(int n){
	int len=0;
	while(n){
		len++;
		n/=10;
	}
	return len;
}
void solve(){
    string a;int b;
    cin>>a>>b;
	int s=0;
    int la=a.length(),lb=get_len(b);
    int now=0;
    for(int i=0;i<la;i++){
        s=s*10+a[i]-'0';
        now++;
        if(now==lb&&s>b||now>lb){
            s%=b;
            now=get_len(s);
        }
    }
    cout<<s<<endl;
}

P1434 [SHOI2002] 滑雪

赛时有道题的原题是这个,是很直观的dfs(⊙﹏⊙),但封榜了才一次过……后悔自己没早点看😢

赛时只会没有一点剪枝的dfs……不过赛后也补了记忆化的写法,结合我原来的写法,对记忆化搜索更熟悉了一点吧(?)

代码1(纯暴力,会t)

int a[N][N],v[N][N],n,m,out;
int op[4][2]={0,1,0,-1,1,0,-1,0};
void dfs(int x,int y,int step){
    int f=1;
    rep(k,0,3){
        int nx=x+op[k][0],ny=y+op[k][1];
        if(v[nx][ny]||a[nx][ny]>=a[x][y]||nx<1||ny<1||nx>n||ny>n) continue;
        v[nx][ny]=1;
        f=0;
        dfs(nx,ny,step+1);
        v[nx][ny]=0;
    }
    if(f){
        out=max(out,step);
    }
}
void solve(){
    cin>>n>>m;
    rep(i,1,n){
        rep(j,1,m){
            cin>>a[i][j];
            v[i][j]=0;
        }
    }
    int ans=0;
    rep(i,1,n){
        rep(j,1,m){
            out=0;
            dfs(i,j,1);
            //cout<<out<<" ";
            ans=max(out,ans);
        }
    }
    cout<<ans;
}   

代码2(记忆化搜索)

const int N=5e2+5;
int a[N][N],mem[N][N],n,m,out;
int op[4][2]={0,1,0,-1,1,0,-1,0};
int dfs(int x,int y){
    if(mem[x][y]) return mem[x][y];
    mem[x][y]=1;
    rep(k,0,3){
        int nx=x+op[k][0],ny=y+op[k][1];
        if(a[nx][ny]>=a[x][y]||nx<1||ny<1||nx>n||ny>n) continue;
        dfs(nx,ny);
        mem[x][y]=max(mem[x][y],mem[nx][ny]+1);
    }
    return mem[x][y];
}
void solve(){
    cin>>n;
    rep(i,1,n){
        rep(j,1,n){
            cin>>a[i][j];
            mem[i][j]=0;
        }
    }
    int ans=0;
    rep(i,1,n){
        rep(j,1,n){            
            cout<<dfs(i,j)<<" ";
        }
        cout<<endl;
    }
    cout<<endl;
}   

2.二进制王国

拼接字符串使得字典顺序最小,需要重定义排序规则

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
string s[N];
int main()
{
  int n;cin>>n;
  for(int i=0;i<n;i++){
    cin>>s[i];
  }
  sort(s,s+n,[](string &a,string &b){
    return a+b<b+a;//lamda表达式重定义排序规则
  });
  for(int i=0;i<n;i++) cout<<s[i];
  return 0;
}

3.djwcb

知识点

高精度模法——实际是在模拟除法的过程得余数

$res=(res*10+p[i]-'0')%mod;$

    string s;int mod;cin>>s>>mod;
    int l=p.length();
    int res=0;
    rep(i,0,l-1){
        res=res*10+p[i]-'0';
        res%=4;
    }   
    cout<<res;

分析

$x^n的个位以4为周期$

代码

void solve(){
    int x;string p;
    cin>>x>>p;
    x%=10;
    int l=p.length();
    int s=0;
    rep(i,0,l-1){
        s=s*10+p[i]-'0';
        s%=4;
    }    
    if(!s) s=4;
    int res=1;
    while(s--){
        res*=x;
    }
    cout<<res%10;
    cout<<endl;
}

5.无理数位数查询

细节很多的模拟题

思路

已知m进制下的k位数数字个数为$k(m-1)m^{k-1}$,则记m进制下的i位数为f(i),我们对f(i)求前缀和p[i]

  • 用$while(p[k]<n)k++;$就可以得到第n个数是k位数

  • 再利用$cur=(n-p[k-1]+k-1)/k$ 可以得到第n个数是k位数下第cur个整数

  • 由$cur+=m^{k-1}$ 可以得到第n个数是m进制下的第cur个整数

  • 而$w=(n-p[k-1]+k-1)%k$ 则可以得到它是k位数下第cur个整数的第w位(从高位起)

最后再做一下进制转换,把cur转换为m进制数,我们的答案就是转换后的从高位起的第w个数

代码

const int N=66;
int a[N],p[N];
int m;
int qpow(int b,int p){
	int res=1;
	while(p){
		if(p&1) res*=b;
		b=b*b;
		p>>=1;
	}
	return res;
}
int f(int k){
	if(k) return (k*(m-1)*qpow(m,k-1));
	else return 0;
}
void solve(){
   	int n;cin>>n>>m;
   	//cout<<qpow(m,0)<<endl; 
   	rep(i,1,66){
   		//cout<<f(i)<<" ";
   		p[i]=p[i-1]+f(i);
   	} 
   	//cout<<endl;
   	int k=1;
   	while(p[k]<n) k++;
   	//cout<<k<<endl;
   	int cur=n-p[k-1];//f(k-1);
   	int w=(cur+k-1)%k+1;//第cur个整数的第w位 
	cur=(cur+k-1)/k;//k位数下第cur个整数 
	//cout<<cur<<" "<<w<<endl; 
	cur+=qpow(m,k-1)-1;//m进制下的第cur个整数 
	//cout<<cur<<endl;
	int e=0;
	while(cur){//进制转换 
		a[++e]=cur%m;
		cur/=m;
	}
//	per(i,e,1) cout<<a[i];
//	cout<<endl;
	cout<<a[e-w+1]<<endl;
}


1815: 斐波那契数列推论

学长推荐的矩阵快速幂

const int M=10007;
struct matrix{
    int c[3][3];
    matrix(){
        memset(c,0,sizeof(c));
    }
}F,A;
matrix operator*(matrix &a,matrix &b){
    matrix t;
    rep(i,1,2){
        rep(j,1,2){
            rep(k,1,2){
                t.c[i][j]=(t.c[i][j]+a.c[i][k]*b.c[k][j])%M;
            }
        }
    }
    return t;
}
void qpow(int n){
    F.c[1][1]=F.c[1][2]=1;
    A.c[1][1]=A.c[1][2]=A.c[2][1]=1;
    while(n){
        if(n&1) F=F*A;
        A=A*A;
        n>>=1;
    }
}
int f(int n){
    if(!n) return 0;
    if(n<=2){
        return 1;
    }
    mem(F.c),mem(A.c);
    qpow(n-2);
    return F.c[1][1];
}
void solve(){
    int s,t;
    while(cin>>s>>t){
        if(s>t) swap(s,t); 
        //cout<<f(s)<<" "<<f(t)<<endl;
        int ans=(f(t)*f(t+1)%M-f(s-1)*f(s)%M+M)%M;
        cout<<ans<<endl;        
    }
}

E - Insert or Erase (atcoder.jp)

链表

map<int,int>l,r;//节点的前驱与后驱 
void solve(){
	int n,op,x,y;cin>>n;
	rep(i,1,n) cin>>a[i];
	rep(i,1,n){
		l[a[i]]=a[i-1];
		r[a[i]]=a[i+1];
	}
	r[a[n]]=-1,l[a[1]]=-114514;
	r[-114514]=a[1];
	int q;cin>>q;
	while(q--){
		cin>>op>>x;
		if(op==1){
			cin>>y;
			r[y]=r[x];
			l[y]=x;
			l[r[x]]=y;
			r[x]=y;
		}
		else{
			l[r[x]]=l[x];
			r[l[x]]=r[x];
		}
	}
	int now=-114514;
	while(r[now]!=-1){
		now=r[now];
		cout<<now<<" ";
	}
}

C. Beautiful Triple Pairs

容斥原理

假设有两个集合A和B,我们想要求出这两个集合的并集的大小。根据容斥原理,我们不能简单地将A和B的大小相加,因为这样可能会重复计算一部分元素。

容斥原理告诉我们,要求A和B的并集的大小,我们首先要将A和B的大小相加,然后减去A和B的交集的大小,即:

$|A ∪ B| = |A| + |B| - |A ∩ B|$

这样我们就可以避免重复计算,得到A和B的并集的大小。

/*
8
2 1 1 2 1 1 1 1
2 1 1
1 1 2
1 2 1
2 1 1	ans+=3,ans-=3;
1 1 1	ans+=1+1+2,ans-=0;
1 1 1	ans+=2+2+3,ans-=1*3;
*/
void solve(){
	int n;cin>>n;
	rep(i,1,n) cin>>a[i];
	map<array<int,3>,int>cnt;
	map<pair<int,int>,int>mp1,mp2,mp3;
	int ans=0;
	rep(i,1,n-2){
		ans+=mp1[{a[i],a[i+1]}]++;
		ans+=mp2[{a[i],a[i+2]}]++;
		ans+=mp3[{a[i+1],a[i+2]}]++;
		ans-=cnt[{a[i],a[i+1],a[i+2]}]*3ll;
		cnt[{a[i],a[i+1],a[i+2]}]++;
		//cout<<mp1[{a[i],a[i+1]}]<<" "<<mp2[{a[i],a[i+2]}]<<" "<<mp3[{a[i+1],a[i+2]}]<<endl;
		//cout<<cnt[{a[i],a[i+1],a[i+2]}]<<"  "<<ans<<endl;
	}
	cout<<ans<<endl;
}

D-小蓝的二进制询问_河南萌新联赛2024第(一)场:河南农业大学

求[l,r]内二进制下1的个数的和

const int M=998244353;
int fp(int b,int p){
    if(p<0) return 0;
    int res=1;
    while(p){
        if(p&1) res=(b*res)%M;
        b=(b*b)%M;
        p>>=1;
    }
    return res;
}
void solve(){
	int l,r;cin>>l>>r;
	auto calc=[&](int n) -> int{
	    if(n<=1) return n;
	    int res=0,tmp=n;
	    per(i,61,0){
	        if((n>>i)&1){
	            res=((res+i*fp(2,i-1)%M)%M+1)%M+(M+tmp-fp(2,i))%M;
                res%=M;
	            tmp=(M+tmp-fp(2,i))%M;
	            if(tmp==0) break;
	        }
	    }		
	    return res%M;
	};	
	cout<<(M+calc(r)-calc(l-1))%M<<endl;
}

C - Make Them Narrow (atcoder.jp)

很经典的枚举

[SCOI2009]游戏

LCM 完全背包

tokitsukaze and Soldier

学长推荐的思维题

我还要遇见几个你

需要求组合数

比大小 (hard version)

字符串哈希,类似于将字符串作进制数转换,hash[i]=hash[i-1]*131+a[i];

同时需要储存每位进制

posted @ 2024-03-08 07:43  mono_4  阅读(4)  评论(0编辑  收藏  举报