【2020省选模拟】题解

T1:

显然每次选最大的减去一定不劣
考虑先 d p dp dp f / g [ i ] [ j ] [ k ] f/g[i][j][k] f/g[i][j][k]表示最小的前 i i i位,除了个位其他都是 9 9 9, i i i位后最大的字母是 j j j,个位是 k k k将最后 i i i为的值删到 < 0 <0 <0的最小次数和为哪个负数
具体 d p dp dp过程可以看代码

然后可以先把数减到 99999.... k ‾ \overline{99999....k} 99999....k
然后直接计算即可

具体看代码扯不清楚

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
ll f[21][11][11];
int n,g[21][11][11],dig[20];
char str[20];
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=readstring(str);
	for(int i=1;i<=n;i++)dig[n-i+1]=str[i]-'0';
	for(int i=0;i<=9;i++)
	for(int j=0;j<=9;j++){
		if(i>j)f[1][i][j]=1,g[1][i][j]=10-i+j;
		else f[1][i][j]=2,g[1][i][j]=10-i;
	}
	for(int i=2;i<=18;i++)
	for(int j=0;j<=9;j++)
	for(int k=0;k<=9;k++){
		g[i][j][k]=k;
		for(int p=9;~p;p--)
		f[i][j][k]+=f[i-1][max(j,p)][g[i][j][k]],g[i][j][k]=g[i-1][max(j,p)][g[i][j][k]];
	}
	int now=dig[1];ll res=0;
	for(int i=2;i<=n;i++){
		while(dig[i]!=9){
			int mx=0;
			for(int j=i;j<=n;j++)chemx(mx,dig[j]);
			if(!mx)break;
			res+=f[i-1][mx][now];
			now=g[i-1][mx][now];
			dig[i]--;
			for(int j=i;dig[j]<0;j++){
				dig[j]=9,dig[j+1]--;
			}
		}
	}
	for(int i=n;i>1;i--){
		while(dig[i])
		res+=f[i-1][dig[i]][now],now=g[i-1][dig[i]][now],dig[i]--;
	}
	if(now)res++;
	cout<<res<<'\n';
	return 0;
}

T2:

冷静一下发现是扫描线板子

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define bg begin
#define pii pair<int,int>
#define fi first
#define cs const
#define se second
#define pb push_back
#define y1 shinkle
cs int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
inline int read(){
	char ch=gc();
	int res=0;bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=100005;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int adj[N],nxt[N<<1],to[N<<1],ecnt;
inline void addedge(int u,int v){
	nxt[++ecnt]=adj[u],adj[u]=ecnt,to[ecnt]=v;
}
int fa[N][18],in[N],out[N],dfn,dep[N];
void dfs1(int u){
	in[u]=++dfn,dep[u]=dep[fa[u][0]]+1;
	for(int i=1;i<=17;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
	for(int e=adj[u],v;e;e=nxt[e]){
		v=to[e];if(v==fa[u][0])continue;
		dep[v]=dep[u]+1,fa[v][0]=u;
		dfs1(v);
	}out[u]=dfn;
}
inline int Lca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int i=17;~i;i--)if(dep[fa[u][i]]>=dep[v])u=fa[u][i];
	if(u==v)return u;
	for(int i=17;~i;i--)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
	return fa[u][0];
}
inline int jump(int u,int k){
	for(int i=17;~i;i--)if(k&(1<<i))u=fa[u][i];
	return u;
}
struct way{
	int x,y,lca;
	friend inline bool operator <(cs way &a,cs way &b){
		return dep[a.x]+dep[a.y]-2*dep[a.lca]>dep[b.x]+dep[b.y]-2*dep[b.lca];
	}
}p[N];
int n,m;
struct opt{
	int l,r,coef;
};
vector<opt> q[N];
vector<int> upd[N];
inline void addquery(int lx,int rx,int ly,int ry){
	opt nd;
	//cout<<lx<<" "<<rx<<" "<<ly<<" "<<ry<<'\n';
	nd.l=ly,nd.r=ry,nd.coef=-1;
	q[lx-1].pb(nd),nd.coef=1;
	q[rx].pb(nd);
}
inline void addupd(int x,int y){
	upd[x].pb(y);
}
namespace bit{
	int tr[N];
	#define lb(x) (x&(-x))
	inline void update(int p,int k){
		for(;p<=n;p+=lb(p))tr[p]+=k;
	}
	inline int qry(int p,int res=0){
		for(;p>0;p-=lb(p))res+=tr[p];return res;
	}
	inline int query(int l,int r){
		return qry(r)-qry(l-1);
	}
}
int main(){
	#ifdef Stargazer
	#endif
	n=read(),m=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		addedge(u,v),addedge(v,u);
	}dfs1(1);
//	for(int i=1;i<=n;i++)cout<<in[i]<<" "<<out[i]<<'\n';
	for(int i=1;i<=m;i++){
		int u=read(),v=read(),lca=Lca(u,v);
		if(in[u]>in[v])swap(u,v);
		if(lca!=u&&lca!=v){
			addquery(in[u],out[u],in[v],out[v]);
		}
		else{
			if(lca==v)swap(u,v);
			int t=jump(v,dep[v]-dep[u]-1);
			//,cout<<"Have problem\n";
			if(in[t]>1)addquery(1,in[t]-1,in[v],out[v]);
			if(out[t]<n)addquery(in[v],out[v],out[t]+1,n);
		}
		addupd(in[u],in[v]);
	//	addupd(in[v],in[u]);
	}
	ll res=0;
	for(int i=1;i<=n;i++){
		for(int j=0;j<upd[i].size();j++){
			bit::update(upd[i][j],1);
		}opt x;
		for(int j=0;j<q[i].size();j++){
			x=q[i][j];
			res+=x.coef*bit::query(x.l,x.r);
		}
	}res-=m;
	if(res==0){
		puts("0/1");
	}
	else{
		ll fm=1ll*m*(m-1)/2;
		ll g=gcd(fm,res);
		res/=g,fm/=g;
		cout<<res<<"/"<<fm<<'\n';
	}
	return 0;
}

T3:

见此

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值