关于北航程设考试题目的一点研究

image

评价

没想到北航程设题竟然这么有实力,难怪有人会作弊

一种可能是对的做法

不难想到一个贪心,每次都作弊,直到不能作弊时,就停止作弊
然后接下来想到直接二分作弊次数,然后剩下的时间都不作弊,判断就看最终警觉值会不会\(<L\)
仔细一想,因为警觉值应该不能为负数,所以有可能不作弊时减去\(y\)时,\(y\)不能完全减去
这样前面的做法就有问题
再思考,每次减到\(0\)后,接下来就会不断地循环这个过程,我们可以找到循环的长度,多余的部分就可以直接套用前面的做法
剩下的问题就转化成了\(tx\%y\ge L-x\),求最小的\(t\),若\(tx\%y+x\ge L\),这时候必须额外减去一个y来清零,如果不存在这样的\(t\),就可以直接套用前面的做法
\(p=L-x,x=x\%y,t'=\lfloor\frac{p}{x}\rfloor\)

  • \(t'x\ge p\),则\(t'\)为最小的\(t\)
  • \((t'+1)x\%y\ge p\),则\(t'+1\)为最小的\(t\)
  • 否则\((t'+1)x\%y=(t'+1)x-y<p\)

\(dx=(t'+1)x-y\),显然有\(dx<x,y-p<x\)

  • \(dx=0\),则\(t\)不存在
  • \(dx\not=0\),那么可以考虑每次在\(t'x\)的基础上每次\(t'x+(t'+1)x\%y\),相当于每次\(+dx\),如果\(+dx\)超过了\(y\),就再加一次\(t'x\),这样问题就转化成了求\(t\cdot dx\%(y-t'x)\ge p-t'x\),最小的\(t\)的问题,递归求解即可,因为\(y-t'x=y\%x\),所以时间复杂度是\(O(\log n)\)的,证明参考辗转相除法

补充

对于为什么最后的转化是对的,我又稍微写了点证明
\(k\in[t'x,y)\),表示当前的值

  • 如果\(k+dx<y\),这时\((t'+1)x\),是一定要加上的,这种情况不会有问题
  • 如果\(k+dx\ge y\)\((k+dx)\%y=k+dx-y<dx<x\),所以有\(dx+(t'-1)x<t'x\)
    这说明我们在通过加上\((t'+1)x\),并且取模之后,不可能通过加上\(t''x(t''<t')\),使得\(k\)再次\(\in[t'x,y)\),所以取摸后\(t'x\)是一定要加上的

这样就证明了转化是正确的

代码实现

只实现了求\(tx\%y\ge p\),最小值\(t\)的函数,随便拍了一些小数据,应该问题不大

点击查看代码
#include<cstdio>
using namespace std;
int get(int x,int y,int p)
{
	for(int t=1;t<=y;t++)
	{
		int res=t*x%y;
		if(res>=p)
			return t;
	}
	return 0;
}
int dfs(int x,int y,int p)
{
	if(p>=y) return 0;
	x%=y;
	if(x==0) return 0;
	int t=p/x;
	if(t*x>=p) return t;
	if(t*x+x<y) return t+1;
	int dx=t*x+x-y;
	if(dx==0) return 0;
//	printf("xyp %d %d %d %d\n",dx,y-t*x,p-t*x,get(dx,y-t*x,p-t*x));
	int rest=dfs(dx,y-t*x,p-t*x);
//	int rest=get(dx,y-t*x,p-t*x);
	if(rest==0) return 0;
	return t+rest*(t+1)+(dx*rest/(y-t*x))*t;
}
int main()
{
//	printf("%d\n",17*30%99);
	for(int i=13;i<=13;i++)
	{
		for(int j=i+1;j<=500;j++)
			for(int k=1;k<=500;k++)
			{
//				if(get(i,j,k)!=0)
//				{
					if(get(i,j,k)!=dfs(i,j,k))
						printf("ijk %d %d %d get %d dfs %d\n",i,j,k,get(i,j,k),dfs(i,j,k));	
//				}
			}
	}
	return 0;
	//30 99 96 get 23 dfs 17
//	printf("%d %d\n",30*23%99,30*29%99);
//	return 0;
	int x=30,y=99,p=96;
	printf("%d %d\n",get(x,y,p),dfs(x,y,p));
	return 0;
}
posted @ 2024-11-14 00:10  _doctorZ  阅读(114)  评论(0编辑  收藏  举报