CF1498

A.GCD Sum

CF原题链接

题目大意:

我们用\(sum_{1}\)表示\(n\)的数位之和,定义\(gcdSum(x)=gcd(x,sum_{1})\)

给出\(t\)组数据,每组数据给出\(n\),要求找到最小的整数\(x\),使其满足\(x\geqslant n\)\(gcdSum(x)>1\)\((1\leqslant t\leqslant 10^{4},1\leqslant n\leqslant 10^{18})\)

解题思路:

第一眼:我丸辣

第二眼:你丸辣

虽然这题看上去不好做,但我们可以想到小学就知道的一件事:若\(x\)的数位之和是\(3\)的倍数,那么\(x\)一定也是\(3\)的倍数,对应到这道题中就是此时一定\(gcdSum(x)\geqslant 3>1\)

那么也就是说,对于每一个给出的数\(n\),我们最多往上枚举3次就一定能找到答案,敲个暴力嗨皮恩定

可爱的小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
int T;
int n;

int gcd(int x,int y)
{
	if (y==0) return x;
	return gcd(y,x%y);
}
signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		scanf("%lld",&n);
		n--;
		int sum,x;
		do
		{
			n++;
			x=n,sum=0;
			while (x)
			{
				sum+=x%10;
				x/=10;
			}
		}while(gcd(n,sum)<=1);
		printf("%lld\n",n);
	}
	return 0;
}

B.Box Fitting

CF原题链接

题目大意:

\(t\) 组数据,每组数据给定\(n\)个长度为\(w\)、高度为\(1\)的长方形,给出盒子的长度\(W\)(保证\(w\)\(2\)的幂)。要求求出盒子可放下所有长方形的最小高度,长方形不能重叠、不能立着放。\((1\leqslant t\leqslant 5000,1\leqslant \Sigma n\leqslant 10^{5},1\leqslant W\leqslant 10^{9},1\leqslant w\leqslant 10^{6})\)

解题思路:

第一眼:丸辣

第二眼:吗

第三眼:真丸辣

显然,我们可以想到每次肯定把长度大的放进去,若放不进去,那必然要多开一行。

于是乎,只需要将\(w_{i}\)从大到小排序,再用大根堆维护目前空余的最大值,若当前\(w_{i}\)放不进去,那就多开一行,若放得进去,更新一下当前使用的空间就行。

坏代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int T;
int n,w;
int p[N];
priority_queue <int> q;
int l;

bool cmp(int a,int b) {	return a>b; }
signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		while (!q.empty()) q.pop();
		q.push(0);
		l=0;
		scanf("%lld%lld",&n,&w);
		for (int i=1;i<=n;i++) scanf("%lld",&p[i]);
		sort(p+1,p+1+n,cmp);
		for (int i=1;i<=n;i++)
		{
			int t=q.top();
			if (t<p[i])
			{
				l++;
				q.push(w-p[i]);
				continue;
			}
			q.pop(); 
			q.push(t-p[i]);
		}
		printf("%lld\n",l);
	}
	return 0;
}

C. Planar Reflections

CF原题链接

题目大意:

\(t\)组数据,每组数据给出\(n\)\(k\),表示共有\(n\)个平面与一个等级为\(k\)的粒子。

对与每个能级为\(k\)的粒子,当它穿过一个平面时,会向相反方向产生一个能级为\(k-1\)的粒子,自己方向、能级不变。当一个粒子能级为\(1\)时,不会再产生新的粒子。

求能级为\(k\)的粒子穿过\(n\)个平面后一共有多少个粒子。\((t\leqslant 100,\Sigma n,\Sigma k\leqslant 1000)\)

解题思路:

大概手模一下过程之后容易想到递归。\(f_{i,j,k}\)表示对于正在穿第\(i\)个平面、能级为\(j\)、方向为\(k\)的粒子,最后会由它引发出多少粒子。递归式也很好想到,这里就不写了,可以看代码(其实是懒得打字……)

数据量不大,但可以加上记忆化,不然递归会死掉!!

可爱的小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010;
const int MOD=1e9+7;
int T;
int n,k;
int f[N][N][2];
//1为右,0为左 
int fd(int num,int lev,int d)
{
	if (f[num][lev][d]) return f[num][lev][d];
	if (lev==1||num==0||num==n+1) return f[num][lev][d]=1;//很明显的边界
	if (d==1) return f[num][lev][d]=(fd(num-1,lev-1,0)+fd(num+1,lev,1))%MOD;//不同方向要分类讨论
	else return f[num][lev][d]=(fd(num-1,lev,0)+fd(num+1,lev-1,1))%MOD;
}
signed main()
{
	scanf("%lld",&T);
	while (T--)
	{
		memset(f,0,sizeof f);//为什么不清空会wa掉呢?因为边界条件不同啦……
		scanf("%lld%lld",&n,&k);
		printf("%lld\n",fd(1,k,1));
	}
	return 0;
}

D.Bananas in a Microwave

CF原题链接

题目大意:

有一个\(k\)值,初始化为\(0\);给出\(n\)个操作,每个操作给出三个参数\(t,x,y\)

对于\(t=1\)\(x_{0}=x/10^{5}\),可执行不超过\(y\)次变换使得\(k=\lceil k+x_{0}\rceil\)

对于\(t=2\)\(x_{0}=x/10^{5}\),可执行不超过\(y\)次变换使得\(k=\lceil k\times x_{0}\rceil\)

给出\(m\)个询问,对于第\(i\)个询问回答\(k=i\)最早在哪个操作出现,若无法达到则输出\(-1\)\((n\leqslant 200,m\leqslant 10^{5},x_{0}\leqslant m)\)

解题思路:

若不看数据范围,我们duck直接暴力模拟,但暴力复杂度不是说着玩的,于是乎我们想到\(dp\)

设状态\(f_{i}\)表示\(k=i\)最早达到的操作数,\(g_{i}\)表示当前操作使得\(k=i\)的所需操作数。那么就很好转移了,\(g_{\lceil k+x_{0}\rceil}=min(g_{\lceil k+x_{0}\rceil},g_{k}+1)\),对于合法的\(g_{i}\)\(f_{i}=cnt\)\(cnt\)表示当前的操作数)

不做评价的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m;
int f[N],g[N];
int cnt;

signed main()
{
	memset(f,0x3f,sizeof f);
	scanf("%lld%lld",&n,&m);
	while (n--)
	{
		++cnt;
		int t,x,y;
		scanf("%lld%lld%lld",&t,&x,&y);
		double x0=1.0*x/100000;
		for (int i=1;i<=m;i++)
		{
			if (f[i]!=inf) g[i]=0;//要是已经有答案那就不管了
			else g[i]=inf;
		}
		if (t==1)
		{
			for (int i=0;i<=m;i++)
			{
				int k=ceil(i+x0);
				if (k<=m&&g[i]!=inf) g[k]=min(g[k],g[i]+1);
			}
		}
		else
		{
			for (int i=1;i<=m;i++)
			{
				int k=ceil(1.0*i*1.0*x/100000);
				if (k<=m&&g[i]!=inf) g[k]=min(g[k],g[i]+1);
			}
		}
		for (int i=1;i<=m;i++)
		{
			if (f[i]==inf&&g[i]<=y) f[i]=cnt;//答案转移
		}
	}
	for (int i=1;i<=m;i++)
	{
		if (f[i]==inf) printf("-1 ");
		else printf("%lld ",f[i]);
	}
	return 0;
}

E.Two Houses

CF原题链接
很史的一道交互题,不会不会,咕了咕了


F.Christmas Games

CF原题链接
与“阶梯博弈”有关,不会不会,咕了咕了

posted @ 2024-11-12 15:12  还是沄沄沄  阅读(71)  评论(0编辑  收藏  举报