国庆集训0929-0930(未完成)

在这里插入图片描述

硬币求和 scoins

在这里插入图片描述
【问题描述】
有一排 n n n个纵截面积为 1 1 1的硬币。
这里硬币可以抽象为一个竖立着的圆柱,
纵截面积就是圆柱的左视图面积。
每个硬币面值不一样,第 i i i个硬币面值是 i i i
面值越大的硬币的底面圆面积当然应该越大。
具体地,面值为 i i i的硬币的底面圆面积为 i i i个单位圆的面积;
对于所有硬币的底面圆面积正比于面值。
现在请将 n n n个硬币摞成一座塔,
要求相邻的硬币面值差不超过 。
求这座塔的最小高度。请取整输出。
由于浮点数存在较大的精度误差,只要误差不超过 ∣ 1 ∣ |1| 1即可。

样例

2
0

在这里插入图片描述
题解
在这里插入图片描述
在这里插入图片描述

出题人原汁原味代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rint register int
inline ll rf(){ll r;int s=0,c;for(;!isdigit(c=getchar());s=c);for(r=c^48;isdigit(c=getchar());(r*=10)+=c^48);return s^45?r:-r;}
int main(){freopen("scoins.in","r",stdin), freopen("scoins.out","w",stdout); ll n = rf(), c = sqrtl(n+1.9); return !printf("%lld\n",(c-(c*c>n+1))-1);}
}

在这里插入图片描述

汉诺塔 hanoi

在这里插入图片描述
【问题描述】
给定一个有n个盘子的m阶汉诺塔(有m个柱子),求最小步数。

【输入格式】
第一行输入一个正整数T代表数据组数。接下来 T T T行每行两个正整数 n n n m m m
T T T n n n m m m均小于 1500 1500 1500

【输出格式】
对于每组数据,输出一行一个数字表示最少所需步数。
如果无论如何都无法达到目标,输出 N o No No S o l u t i o n Solution Solution

【输入输出样例】

5
5 3
5 4
31
13

在这里插入图片描述
题解

下方第六行的公式应该是 m i n min min
在这里插入图片描述
在这里插入图片描述

出题人原汁原味代码
#include <bits/stdc++.h>
using namespace std;
#define MAXN 1500
#define ll unsigned long long
#define INFLL 0x3f3f3f3f3f3f3f3fllu
#define rint register int
inline int rf(){int r;int s=0,c;for(;!isdigit(c=getchar());s=c);for(r=c^48;isdigit(c=getchar());(r*=10)+=c^48);return s^45?r:-r;}
int n, m, T; ll f[MAXN+5][MAXN+5]; vector<int> A[MAXN+5];
inline void Mul2(vector<int> &A){A.push_back(0); A[0] *= 2; for(int i = 1; i < (int)A.size(); A[i] = (A[i]<<1)+A[i-1]/10, A[i-1] %= 10, i++); if(!A.back()) A.pop_back();}
int main()
{
	freopen("hanoi.in","r",stdin); freopen("hanoi.out","w",stdout);
	n = MAXN; m = MAXN; A[1].assign(1,2); for(rint i = 2; i <= n; A[i] = A[i-1], --A[i-1][0], Mul2(A[i++])); --A[n][0];
	memset(f,0x3f,sizeof f); memset(f[1]+1,0,n<<3); f[2][1] = 1; {ll s = 2; for(rint i = 1; i <= n; f[3][i] = min(f[3][i],s-1), s = min(s<<1,INFLL+1), i++);}
	for(rint i = 4, j, k; i <= m; i++) for(f[i][1] = 1, j = 2, k = 1; j <= n; f[i][j] = f[i-1][j-k]+(f[i][k]<<1), j++)
		for(; k<j-1 && f[i-1][j-k]+(f[i][k]<<1) > f[i-1][j-k-1]+(f[i][k+1]<<1); ++k);
	for(T = rf(); T--; )
	{
		n = rf(); m = rf(); if(m==1){puts("0"); continue;} if(m==2){puts(n>1?"No Solution":"1"); continue;}
		if(m==3){for(rint i = A[n].size()-1; ~i; putchar(A[n][i]+'0'), i--); putchar('\n'); continue;} printf("%llu\n",f[m][n]);
	}	return 0;
}

在这里插入图片描述

随机子树 tree

【问题描述】
有一棵n个点的树。
每天,随机选择一个连通块(一棵子树),从一个点出发走向另一个点的最短路径巡视,巡视走过的距离是两个点之间唯一最短路径包含的边数。
巡视距离太短,起不到有效检查;巡视距离太长太累。
问: 均匀随机选择一个连通块,有多大概率这一天巡视时有可能走过的最长距离也一定在 [ L , R ] [L,R] [L,R]之间。

【输入格式】
只有一行输入三个正整数 n , L , R n,L,R n,L,R
接下来 n − 1 n-1 n1行,每行两个正整数 u , v u,v u,v表示 u , v u,v u,v之间有一条边。保证输入是一棵树。
【输出格式】
只有一行输出一个整数。为 m o d 998244353 mod 998244353 mod998244353意义下的概率。即如果答案可以表示成最简分数 p q \frac{p}{q} qp

请输出 p p p ∗ * q − 1 q^{-1} q1 m o d mod mod 998244353 998244353 998244353,其中 q − 1 q^{-1} q1代表模意义下逆元。

【输入输出样例】

5 2 3
1 2
1 3
3 4
3 5
528482305

在这里插入图片描述
题解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

出题人原汁原味代码
#include <bits/stdc++.h>
using namespace std;
#define MAXN 200000
#define MOD 998244353
#define lc(p) (p<<1)
#define rc(p) (p<<1|1)
#define ad(p) t[p][0]
#define ml(p) t[p][1]
#define mid (lef+rig>>1)
#define MUL(p,k) (k^1 ? ad(p) = 1ll*ad(p)*k%MOD, ml(p) = 1ll*ml(p)*k%MOD : 0)
#define LZ(p) (MUL(lc(p),ml(p)), MUL(rc(p),ml(p)), ml(p) = 1)
#define PS(p) (ad(p) = (ad(lc(p))+ad(rc(p)))%MOD)
#define Auto(v,j) for(vector<int>::iterator j = v.begin(); j != v.end(); j++)
#define rint register int
inline int rf(){int r;int s=0,c;for(;!isdigit(c=getchar());s=c);for(r=c^48;isdigit(c=getchar());(r*=10)+=c^48);return s^45?r:-r;}
inline int fxp(int s, int n=MOD-2){int a=1;for(;n;n&1?a=1ll*a*s%MOD:0,s=1ll*s*s%MOD,n>>=1);return a;}
int n, Le, Ri, K, Ans, t[524288][2], d[MAXN+5], md[MAXN+5], pos[MAXN+5]; vector<int> e[MAXN+5]; inline bool cmp(int x, int y){return md[x]>md[y];}
void BD(int p, int lef, int rig){ml(p)=1,ad(p)=0,lef^rig?BD(lc(p),lef,mid),BD(rc(p),mid+1,rig),0:0;}
void AD(int p, int lef, int rig, int x, int v){lef^rig?LZ(p),x<=mid?AD(lc(p),lef,mid,x,v):AD(rc(p),mid+1,rig,x,v),PS(p):ad(p)=(ad(p)+v)%MOD;}
int QU(int p, int lef, int rig, int L, int R){return L^lef||R^rig?LZ(p),((L<=mid?QU(lc(p),lef,mid,L,min(mid,R)):0)+(R>mid?QU(rc(p),mid+1,rig,max(L,mid+1),R):0))%MOD:ad(p);}
void MU(int p, int lef, int rig, int L, int R, int k){L^lef||R^rig?LZ(p),L<=mid?MU(lc(p),lef,mid,L,min(mid,R),k),0:0,R>mid?MU(rc(p),mid+1,rig,max(L,mid+1),R,k),0:0,PS(p):MUL(p,k);}
void DFS1(int p, int fa){if(fa) e[p].erase(find(e[p].begin(),e[p].end(),fa)); md[p] = d[p] = d[fa]+1; Auto(e[p],j) DFS1(*j,p), md[p] = max(md[p],md[*j]);}
void DFS2(int p){sort(e[p].begin(),e[p].end(),cmp); pos[p] = ++n; Auto(e[p],j) DFS2(*j);}
void DFS3(int p){
	static int k[MAXN+5], f[MAXN+5]; static map<int,int> G; int X = md[p]-d[p], Y, v, _; AD(1,1,n,pos[p],1);
	Auto(e[p],j){DFS3(v=*j); if(j==e[p].begin()) continue; Y = md[v]-d[v]; G.clear(); G[0] = 1; G[X+1] = 0; _ = 0;
		for(rint y = 0; y <= Y && y < K; k[y] = QU(1,1,n,pos[p],pos[p]+min(y,K-y-1)), f[y] = QU(1,1,n,pos[v]+y,pos[v]+y), y++);
		for(rint y = 0; y <= Y && y < K; y+1<K-y?(G[y+1]+=f[y])%=MOD,(G[min(K-y,X+1)]+=MOD-f[y])%=MOD:0, y++);
		for(map<int,int>::iterator a = G.begin(), b = ++G.begin(); b != G.end(); a++, b++)
			_ = (_+a->second)%MOD, MU(1,1,n,pos[p]+a->first,pos[p]+b->first-1,_);
		for(rint y = 0; y <= Y && y < K; AD(1,1,n,pos[p]+y+1,1ll*k[y]*f[y]%MOD), y++);
	}	Ans = (Ans+QU(1,1,n,pos[p],pos[p]+min(K,X)))%MOD;
}
int Work(int _K){BD(1,1,n); K = _K; Ans = 0; DFS3(1); return Ans;}
int main(){
	freopen("tree.in","r",stdin), freopen("tree.out","w",stdout);
	n = rf(); Le = rf(); Ri = rf(); for(rint i = 1, u, v; i < n; u = rf(), v = rf(), e[u].push_back(v), e[v].push_back(u), i++);
	DFS1(1,0); n = 0; DFS2(1); return !printf("%d\n",1ll*fxp(Work(n))*(Work(Ri)-Work(Le-1)+MOD)%MOD);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

出题人代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=510;int a[N][N],b[N][N],s[N][N];
inline int _init(int n)
{
	rep(i,1,n) rep(j,1,n) if((i-2*j)%5==0) s[i][j]=1;
	rep(i,1,n) rep(j,1,n) s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
	return 0;
}
inline int S(int xl,int xr,int yl,int yr) { return s[xr][yr]-s[xl-1][yr]-s[xr][yl-1]+s[xl-1][yl-1]; }
int main()
{
	freopen("landmine.in","r",stdin); freopen("landmine.out","w",stdout);
	int n=inn(),m=inn(),rev=0,ans=0;if(n>m) swap(n,m),rev=1;
	if(n<5) { ans=n*(m/5);rep(i,1,n) rep(j,1,m) a[i][j]=!(j%5); }
	else{
		int t=10;ans=n*m/5,_init(max(n,m)+t);
		rep(i,1,t) rep(j,1,t) if(S(i,i+n-1,j,j+m-1)==ans)
		{
			rep(p,1,n) rep(q,1,m) a[p][q]=S(i+p-1,i+p-1,j+q-1,j+q-1);break;
		}
	}
	printf("%d\n",ans);
	if(rev) { swap(n,m);rep(i,1,n) rep(j,1,m) b[i][j]=a[j][i]; }
	else rep(i,1,n) rep(j,1,m) b[i][j]=a[i][j];
	rep(i,1,n) rep(j,1,m) a[i][j]=b[i][j];
	rep(i,1,n) { rep(j,1,m) printf("%d",a[i][j]);printf("\n"); }
	rep(i,1,n) rep(j,1,m)//check if it's right ( RE if wrong )
	{
		int zc;
		zc=0;if(i+4<=n) rep(k,0,4) zc+=(a[i+k][j]==0);assert(zc<5);
		zc=0;if(j+4<=m) rep(k,0,4) zc+=(a[i][j+k]==0);assert(zc<5);
		zc=0;if(i+4<=n&&j+4<=m) rep(k,0,4) zc+=(a[i+k][j+k]==0);assert(zc<5);
		zc=0;if(i+4<=n&&j-4>=1) rep(k,0,4) zc+=(a[i+k][j-k]==0);assert(zc<5);
	}
	return 0;
}
同班大佬的题解

如果 m , n m,n m,n其中一个小于5,那么必然不会在短边和斜方向上产生“ 5 5 5连”,那么只需要考虑长边就行,随便画一组数据,发现只要逢5出现一个1即可。
如果两者都大于五,就需要思考一种策略。观察样例,如果我们把 “ 5 ∗ 5 ” “5*5” 55作为一个单位矩阵,我们只需要用单位矩阵填充这个大矩形即可,因为单位矩阵相同,那么在横纵上必然不会出现“ 5 5 5连”的情况,只需要保证斜边上不会出现“ 5 5 5连”。
很好,思考出题解了,我们根据样例构建单位矩阵,交上去评测,WA掉了,很好!
为什么呢?因为单位矩阵是不能满足斜边无“ 5 5 5连”的,接着就要手玩单位矩阵辽,玩着玩着单位矩形就出来了……
还有一个矩阵中几个 1 1 1的问题,因为每25个方格的单位矩阵中会有5个1,这是显然的,所以上面特判的公式是 m ∗ n / 5 m*n/5 mn/5,其他情况要用一个cnt记录。

根据题解写的代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;

int n, m, cnt = 0;
int a[505][505]={};
int b[5]={1,4,2,5,3};
int main(){
	scanf("%d%d", &n, &m);
	if(n < 5) {
		printf("%d\n", m*n/5);
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= m; j++){
				if(j % 5 == 0) printf("1");//每出现五个,就添加一个1,保证不出现“5连”
				else printf("0");
			}
			printf("\n");
		}
		return 0;
	}//n小于5的情况,下面同样方法特判m小于5
	if(m < 5) {
		printf("%d\n", m*n/5);
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= m; j++){
				if(i % 5 == 0) printf("1");
				else printf("0");
			}
			printf("\n");
		}
		return 0;
	}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			a[i][j] = 0;
				
	for(int i = 1; i <= n; i++)
		for(int j = b[ i%5 ]; j <= m; j +=5){
			a[i][j] = 1;
            cnt++;
		}//单位矩阵的复制黏贴,好快乐!
    printf("%d\n",cnt);
    
   	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++)
			printf("%d", a[i][j]);
		printf("\n");
	}//输出
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

出题人代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int rf(){int r;int s=0,c;for(;!isdigit(c=getchar());s=c);for(r=c^48;isdigit(c=getchar());(r*=10)+=c^48);return s^45?r:-r;}
const int N=5000010;const lint inf=LLONG_MIN/100;const db eps=1e-9;
int L[N];
namespace GETL{
	// f[i] trans from [ L_i, i ), f[i] = max_{L_i<=j<i} f[j]+calc(i-j), calc(x)=x*(x-1)/2 
	inline int getL(int n)
	{
		rep(i,1,n) L[i]=rf();
		assert(L[1]==0);
		rep(i,1,n-1) assert(L[i]<=L[i+1]);
		return 0;
	}
}
inline int dcmp(db x) { return (x<-eps)?-1:(x>eps); }
struct Line{
	lint k,b;Line(lint _k=0,lint _b=inf) { k=_k,b=_b; }
	inline lint operator()(lint x)const { return k*x+b; }
	inline db getis(const Line &L)const { return -((db)b-L.b)/(k-L.k); }
};
struct Queue{
	int t;Line f[N];inline int clear() { return t=0; }
	inline int add(Line F) { while(t>1&&dcmp(F.getis(f[t])-f[t].getis(f[t-1]))>=0) t--;f[++t]=F;return 0; }
	inline lint query(lint x) { if(!t) return inf;while(t>1&&f[t](x)<=f[t-1](x)) t--;return f[t](x); }
}q;int l[N],r[N];lint f[N];
int main()
{
	freopen("jump.in","r",stdin); freopen("jump.out","w",stdout);
	int n=rf(),bc=0;GETL::getL(n);
	for(int i=0,j=0;i<n;i=++j) { while(j+1<n&&L[j+2]<=i) j++;l[++bc]=i,r[bc]=j; }
	f[0]=0;rep(i,1,n) f[i]=inf;
	rep(i,1,bc)
	{
		q.clear();int k=l[i];
		for(int j=r[i]+1;j>l[i];j--)
		{
			while(k>L[j]) k--,q.add(Line(k,f[k]+k*(k+1ll)/2));
			f[j]=max(f[j],q.query(-j)+j*(j-1ll)/2);
		}
		q.clear();
		rep(j,l[i]+1,r[i]+1) q.add(Line(-(j-1),f[j-1]+(j-1ll)*j/2)),f[j]=max(f[j],q.query(j)+j*(j-1ll)/2);
	}
	return !printf("%lld\n",f[n]<<1);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

出题人代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define mod 998244353
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int rf(){int r;int s=0,c;for(;!isdigit(c=getchar());s=c);for(r=c^48;isdigit(c=getchar());(r*=10)+=c^48);return s^45?r:-r;}
const int N=500010,K=22;
int np[N],p[N],C[K<<1][K<<1],f[K][N],mnp[N],zs[N],clc[K][K];
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int prelude(int n,int mxk)//seems that O(n(lgn)^2) is faster then O(nlgn) QwQ
{
	rep(i,0,mxk) f[i][1]=1;
	rep(i,0,2*mxk) C[i][0]=1;
	rep(i,1,2*mxk) rep(j,1,i) C[i][j]=C[i-1][j-1]+C[i-1][j],(C[i][j]>=mod?C[i][j]-=mod:0);
	rep(i,0,mxk) rep(j,0,mxk) clc[i][j]=C[i+j][i];
	for(int i=2,c=0;i<=n;i++)
	{
		if(!np[i]) { p[++c]=i,mnp[i]=i,zs[i]=1;rep(j,0,mxk) f[j][i]=j+1; }
		rep(j,1,c&&p[j]<=n/i)
		{
			int x=p[j]*i;np[x]=1;
			if(i%p[j]!=0) { mnp[x]=p[j];rep(k,0,mxk) f[k][x]=f[k][i]*(k+1ll)%mod; }
			else{
				mnp[x]=mnp[i]*p[j];int t=x/mnp[x];
				if(x==mnp[x]) { zs[x]=zs[i]+1;rep(k,0,mxk) f[k][x]=clc[k][zs[x]]; }
				else rep(k,0,mxk) f[k][x]=(lint)f[k][t]*f[k][mnp[x]]%mod;break;
			}
		}
	}
	rep(i,0,mxk) rep(j,1,n) f[i][j]+=f[i][j-1],(f[i][j]>=mod?f[i][j]-=mod:0);
	return 0;
}
int y[K],pre[K],suf[K],fi[K];
inline int solve(int *y,int n,int p)
{
	if(p>=mod) p%=mod;if(p<=n) return y[p];int ans=0;
	pre[0]=p,suf[n]=p-n;rep(i,1,n) pre[i]=(lint)pre[i-1]*(p-i)%mod;
	for(int i=n-1;i>=0;i--) suf[i]=(lint)suf[i+1]*(p-i)%mod;
	rep(i,0,n)
	{
		int pr=(i>0?pre[i-1]:1),sf=(i<n?suf[i+1]:1);
		if((n-i)&1) ans=(ans-(lint)y[i]*pr%mod*sf%mod*fi[i]%mod*fi[n-i])%mod,(ans<0?ans+=mod:0);
		else ans=(ans+(lint)y[i]*pr%mod*sf%mod*fi[i]%mod*fi[n-i])%mod;
	}
	return ans;
}
int main()
{
	freopen("easy.in","r",stdin); freopen("easy.out","w",stdout);
	int n=rf(),mxk=rf(),q=rf();prelude(n,mxk=20);
	rep(i,fi[0]=1,mxk) fi[i]=(lint)fi[i-1]*fast_pow(i,mod-2)%mod;
	while(q--)
	{
		int L=rf(),R=rf(),k=rf()-1;
		rep(i,0,mxk) y[i]=f[i][R]-f[i][L-1],(y[i]<0?y[i]+=mod:0);
		printf("%d\n",solve(y,mxk,k));
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值