ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

省选模拟17

2022-02-19 18:01:15  阅读:113  来源: 互联网

标签:ch return 17 省选 res int inline 模拟 define


A. 进制转换

可以把进制转换看成是一个解一个式子

每一项的系数都在 \(0\) 到 \(9\)

考虑 \(b\) 较大时的情况,最高次的值要远大于其他值

于是只考虑这一项带来的限制

\(a_mb^m\leq y \leq a_mb^m+9\times \frac{b^m-1}{b-1}\)

根据这个式子可以解出 \(b\) 的两个取值的范围是,从大到下一次枚举,暴力检验就行

\(b\) 较小时也可以暴力检验

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
inline void write(int x){
	static int stk[42],top;
	while(x) stk[++top]=x%10,x/=10;
	while(top) putchar(stk[top--]+'0');
	putchar('\n');
}
int T,y,lim,b;
int calc(int x,int b){
	int res=0,p=1;
	while(x){if(x%b>9) return -1;res+=x%b*p;x/=b;p*=10;}
	return res;
}
inline void solve(){
	y=read(),lim=read();
	for(int i=log10l(lim);i<=8;i++) for(int j=1;j<=9;j++) for(int r=powl(1.0L*y/j,1.0L/i),l=powl(1.0L*(y-9*(powl(r,i)-1)/(r-1))/(j),1.0L/i);r>=l;r--){
		if(lim<=calc(y,r)){printf("%lld\n",r);return ;}
	}
	for(int i=100;i;i--) if(lim<=calc(y,i)){printf("%lld\n",i);return ;}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("number.in","r",stdin);
	freopen("number.out","w",stdout);
	T=read();while(T--) solve();
	return 0;
}

B. 遇到困难睡大觉

学了退火,加上考场的随机交换能拿 \(80\)

记录最大值和最小值的位置,每次随机一个位置和最大或最小值交换

然后套上退火就行

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define lson rt<<1
#define rson rt<<1|1
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,k,ans=-inf,mx,mn;
struct data{
	int a,b;
	inline bool operator<(const data &B)const{return a==B.a?b>B.b:a>B.a;}
	inline bool operator==(const data &B)const{return a==B.a||b==B.b;}
}L[100010];
inline bool chk(){double t=1.0*clock()/CLOCKS_PER_SEC;return t<2.0;}
mt19937 rd(time(0));
struct Seg{int mn,mx,mnp,mxp;}st[100010*4];
inline void pushup(int rt){
	st[rt].mn=min(st[lson].mn,st[rson].mn);
	st[rt].mx=max(st[lson].mx,st[rson].mx);
	if(st[rt].mn==st[lson].mn) st[rt].mnp=st[lson].mnp;else st[rt].mnp=st[rson].mnp;
	if(st[rt].mx==st[lson].mx) st[rt].mxp=st[lson].mxp;else st[rt].mxp=st[rson].mxp;
}
void build(int rt,int l,int r){
	if(l==r) return st[rt].mn=L[l].a+l*k,st[rt].mx=L[l].b+l*k,st[rt].mnp=l,st[rt].mxp=l,void();
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	pushup(rt);
}
void upd(int rt,int l,int r,int pos){
	if(l==r) return st[rt].mn=L[l].a+l*k,st[rt].mx=L[l].b+l*k,void();
	int mid=(l+r)>>1;
	if(pos<=mid) upd(lson,l,mid,pos);
	else upd(rson,mid+1,r,pos);
	pushup(rt);
}
inline void SA(){
	int nans=-inf;
	double T=1000000;int now,del,typ,p1,p2;
	random_shuffle(L+1,L+1+n);build(1,1,n);nans=st[1].mn-st[1].mx;
	while(T>1e-12){
		typ=rd()%2,p2=rd()%n+1;
		if(typ) p1=st[1].mnp;else p1=st[1].mxp;if(L[p1]==L[p2]){T*=0.99997;continue;}
		swap(L[p1],L[p2]);upd(1,1,n,p1);upd(1,1,n,p2);
		now=st[1].mn-st[1].mx;del=now-nans;
		nans=max(nans,now);
		if(now!=nans&&exp(1.0*del/T)*RAND_MAX<rand()){swap(L[p1],L[p2]);upd(1,1,n,p1);upd(1,1,n,p2);}
		T*=0.99996;
	}
	ans=max(ans,nans);
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("sleep.in","r",stdin);
	freopen("sleep.out","w",stdout);
	n=read(),k=read();
	for(int i=1;i<=n;i++) L[i].b=read(),L[i].a=read();sort(L+1,L+1+n);
	build(1,1,n);ans=max(ans,st[1].mn-st[1].mx);
	while(chk()) SA();
	printf("%lld\n",ans);
	return 0;
}

T3

若不考虑 \(a_i\) 的限制,可以用插板法算出 \(n\) 个钥匙放在 \(m\) 个地方的方案数

考虑 \(a_i\) 的限制就可以强制选 \(a_i+1\) 个然后再用容斥搞,需要乘上 \((-1)^{|S|}\) 的系数

带上 \(p_i\) 的权值也很好求

可以用 \(dp\) 来求这个容斥,设 \(f_{i,x,y,t}\) 表示前 \(i\) 个地点,被发现的地点选择容斥的集合大小为 \(x\) 的方案数, \(y\) 为没有被发现的, 选择了 \(t\) 个地点被发现的概率

然后再求解一共有多少种方案就行

求解方案相当与这样一个问题一共 \(n_1+n_2\) 把钥匙放在 \(m_1+m_2\) 个地点

其中前 \(m_1\) 个地点至少放 \(n_1\) 把

暴力可以直接枚举前面多放几把,然后用插板法求方案

用组合意义换种枚举方法,直接枚举第 \(n_1\) 把钥匙放在哪里,然后再插板法求方案

\(\sum\limits_{k=1}^m1\binom{n_1-1+k-1}{n_1-1}\binom{n_2+M-k}{n_2}\)

然后 \(n_1=n-x\) , \(n_2=N-n-y\) 这个根据上面的 \(dp\) 定义求出

对于不同的 \(n_1,n_2\) 预处理出所有组合数就行

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define mod 998244353
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int m,d,N,lim,n,cur,ans;
int a[110],p[110];
int f[2][110][110][110];
int C1[110][110],C2[110][110];
int inv[110];
//C1[i][j] -> C[n-i*d-1+j-1][n-i*d-1(j-1)]
//C2[i][j] -> C[N-n-i*d+m-j][N-n-i*d(m-j)]
inline int qpow(int x,int k){
	int res=1,base=x;
	while(k){if(k&1) res=res*base%mod;base=base*base%mod;k>>=1;}
	return res;
}
inline int C(int n,int m){int res=inv[m];for(int i=n;i>n-m;i--) res=res*i%mod;return res;}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("key.in","r",stdin);
	freopen("key.out","w",stdout);
	inv[0]=1;for(int i=1;i<=100;i++) inv[i]=inv[i-1]*qpow(i,mod-2)%mod;
	m=read(),d=read(),N=read(),n=read();lim=N/d;
	for(int i=1;i<=m;i++) a[i]=(read()+1)/d,p[i]=read();
	for(int i=0;i<=100;i++) for(int j=0;j<=100;j++){
		C1[i][j]=C(n-i*d-1+j-1,j-1);
		C2[i][j]=C(N-n-i*d+m-j,m-j);
	}
	f[0][0][0][0]=1;
	for(int i=0;i<m;i++,cur^=1){
		memset(f[cur^1],0,sizeof(f[cur^1]));
		for(int j=0;j<=lim;j++) for(int k=0;k<=lim;k++) for(int l=0;l<=i;l++) if(f[cur][j][k][l]){
			(f[cur^1][j][k][l+1]+=f[cur][j][k][l]*p[i+1]%mod)%=mod;
			if(j+a[i+1]<=lim) (f[cur^1][j+a[i+1]][k][l+1]+=mod-f[cur][j][k][l]*p[i+1]%mod)%=mod;
			(f[cur^1][j][k][l]+=f[cur][j][k][l]*(1-p[i+1]+mod)%mod)%=mod;
			if(k+a[i+1]<=lim) (f[cur^1][j][k+a[i+1]][l]+=mod-f[cur][j][k][l]*(1-p[i+1]+mod)%mod)%=mod;
		}
	}
	for(int j=0,n1,n2,v;j<=lim;j++) for(int k=0;k<=lim;k++) for(int l=0;l<=m;l++) if(f[cur][j][k][l]){
		n1=n-j*d;n2=N-n-k*d;if(n2<0||n1+n2<0) continue;v=0;
		if(n1<=0){v=C(n1+n2+m-1,m-1);}else{for(int i=1;i<=l;i++) (v+=C1[j][i]*C2[k][i])%=mod;}
		(ans+=v*f[cur][j][k][l]%mod)%=mod;
	}
	printf("%lld\n",(ans+mod)%mod);
	return 0;
}

标签:ch,return,17,省选,res,int,inline,模拟,define
来源: https://www.cnblogs.com/MaxQAQ/p/15913242.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有