qbxt Day 2

Day 2

考试题解

T1 小路灯

再次签到成功。考试时做法是二分然后加上一点点小贪心。不过这个贪心调了一万年。一开始用半小时写出了“正解”,然后开始写暴力造数据。结果第二组数据就拍出问题了。于是开始调试。调了两个小时才终于调出来,然后开始看(T2)

不过真的就只是二分吗?中间应该还有一些细节要注意。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
ll n,k,minn=2000000005,maxx=0,ans=2000000005;
ll a[100005];
bool check(ll x){
	ll t=a[1],sum=0;
	for(ll i=2;i<=n;i++){
		if(a[i]-t>x){
			sum++;
			t=a[i-1];
			for(ll j=i,k1=i;j<=n;j=k1){
				k1=j;
				while(a[k1]-t<=x&&k1<=n){
					k1++;
				}
				ll k2=k1;
				if(k1>j){
					while(a[k2+1]-a[k1]<=x&&k2+1<=n){
						k2++;
					}
				}
				if(k2>n) break;
				k1=k2;
				sum++;
				t=a[k2];
			}
			break;
		}
	}
	if(sum<=k) return true;
	else return false;
}
int main()
{
	scanf("%lld%lld",&n,&k);
	for(ll i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		minn=min(minn,a[i]);
		maxx=max(maxx,a[i]);
	}
	ll l=0,r=maxx-minn;
	while(l<=r){
		ll mid=(l+r)/2;
		if(check(mid)){
			ans=mid;
			r=mid-1;
		}
		else{
			l=mid+1;
		}
	}
	printf("%lld
",ans);
	return 0;
}

老师做法(没有那么多细节要注意,更好写):在这个距离内往后找,找到一个路灯然后点亮它即可。不需要像我一样考虑前后的最优选择。

类似题目:(NOIp) 2015 D2T1 跳石头

T2 序列

40pts白扔,暴力分-=40。考试的时候真的有点急了,主要是(T1)花费了太多时间。不过这的确是值得的(因为(T1)暴力一分都没有)。暴力模拟就可以得到(40pts)。但是nc写挂了。

40分做法:

暴力模拟。

60分做法:

对每次操作用线段树或者平衡树维护。

100分做法:

发现每一次操作都是将所有的数向后移一位。然后在这种模拟下有特殊情况,每个序列都有(n/k)个数需要挪到每一段后面单独处理,这样总复杂度就是(O(n/1+n/2+n/3+...)=O(n*ln(n))),开一个二倍数组维护即可。


T3 路灯

靠着(T1)对拍用的暴力改了改,水了(60)pts。爆搜就是60分做法。

100做法:

我就知道是(dp),但是我不会。f_{i,j}表示前(i)个路灯点亮了(j)个,而且第(i)个是点亮的。(f_{i,j}=min(f_{r,j-1}+h_{r,i}))。需要提前预处理(h)数组,然后总时间复杂度是(O(n^2*k))

类似题目:(NOIp) 2015 子串(拓展:改成子序列)

(f_{i,j,k}=f_{i-1,j-1,k-1})

T4 匹配

考试由于时间原因写假了且来不及改(20分做法)。

20分做法:

暴力求出两两之间距离然后(n^3)枚举。

40分做法:

暴力求出两两之间的距离(此过程复杂度?),枚举三个点的中间点,然后找到所有与中间点距离为2的点(考试时我也曾有过此思路,但是不太好写)。

100分做法:

一个点与一个子树中距离为2的所有点权和和

树形dp或边加边维护

拓展:洛谷P3565 [POI2014]HOT-Hotels

搜索专题补充

记忆化搜索

实质是(dp)

slots

啥也没听懂?????????

计数

记录13种牌每一种剩多少张,同时记录上一张牌是什么。每当已经搜索过这个状态就不用再搜索了。

优化:用一个数组(a_i)来记录面值相同牌数为i的时候的方案数。

idfs

埃及分数

(s)来记录和,用(a)来记录当前分母,(k)记录个数,然后剪枝:如果(1/a*k<s),那么肯定不行了。而且还要让分母尽可能小。

八数码问题

k短路问题

优先队列,取出队首然后最短路。第(k)次到达就是(k)短路

骑士精神

剪枝:估价函数大于剩余搜索层数。

Lizard 。。。

先搜索出前一半三个人的收益差,然后再搜索后一半,然后比较。然后(Hash)查询(不会)。

随机算法(骗分)

用正确性换取时间复杂度。

爬山算法

(N)个点,有权值,选一个点,使其他点到他的距离 乘上 权值 的和最小。

模拟退火

[HAOI2006]均分数据

???????????????????????????????????????????????????????????????????

例题

背包问题变搜索

(max) (x_1+3x_2+5x_3+9x_4)//价值最大化

(2x_1+3x_2+4x_3+7x_4<=10)//体积

搜索:当前搜到了第几层,剩余体积,得到价值

剪枝:先按价值排序,如果剩余体积乘以当前物品价值仍然小于已得到的价值,那么剪去

货郎问题

剪枝:用(L_i)来记录(i)的出边的最小值,记录当前已走的路径长度,如果长度加上每一个剩余顶点向外连的最小值已经比答案大了,那么直接减去。

邮票面值设计

剪枝:确定一个可选的区间

Tales。。。

求奇最短路和偶最短路((NOIp) 2019 普及组(T4) 加工零件)

建两个图(分层图思想)

NOIp 2014 寻找道路

删掉不符合条件的点然后跑最短路(画图

NOIp 2015 斗地主

按顺序搜索

数论

快速幂

越狱

求出总情况和不会越狱的情况,然后相减得到会越狱的情况。

总:(m^n)

不会越狱:(m*(m-1)^(n-1))

用快速幂求解即可

素数

线性筛

积性函数

莫比乌斯函数:0,n>1;1,n==1

积性函数性质:如果能够求出f(p^k),那么就可以快速地求出f(1)到f(n)。

例题:sigma那个题

看到gcd就枚举。(gcd(i,n)=d -> gcd(i/d,n.d)=1 -> 设i=kd) -> 枚举

??????????????????????????????

逆元

(xy≡1(mod n))

(x)在模(n)意义有逆元当且仅当((x,n)=1)

(a=[n/x],b=x%a)

(ax+b=0(mod n))

(ax=-b)

(ax*b^{-1}=-b*b^{-1})

(ax*b^{-1}=-1)

(-ax*b^{-1}=1(mod n))

所以(x)的逆元是(-a*b^{-1})

线性求逆元代码

inv[1]=1;
for(i=2;i<=n-1;i++)
   inv[i]=(n-inv[n%i]*(n/i)%n)%n;

(O(1))计算组合数(模意义下)

Lucas定理

(P)是质数,则(C_n^m)%(P)= (C_{nmodP}^{mmodP}) * (C_{n/P}^{m/P}) % (P)
常用来求(n),(m)较大,但(P)较小的组合数取模

最大公约数和最小公倍数

定理: (ab = gcd(a,b) * lcm(a,b))

求最大公约数:利用公式(gcd(a, b)=gcd(b, a mod b)), 时间复杂度为(O(logb))

威尔逊定理:若(p)为素数,则((p-1)!≡-1 (mod p))

费马小定理:(p)是素数且((a,p)=1),则(ap-1≡1 (mod p))

线性求欧拉函数:

void eular(int n)
{for(int i=2;i<=n;i++)
     {if (!IsPrime[i])
         {	prime[++cnt]=i;  phi[i]=i-1;}
	  for(int j=1;j<=cnt;j++)
          { if (prime[j]*i>n) break;
       	 Isprime[prime[j]*i]=1;
      	 if (i%prime[j]==0)
               {phi[i*prime[j]]=phi[i]*prime[j];  break;}
      	 else
               phi[i*prime[j]]=phi[i]*(prime[j]-1);
          }
	 }
}

Euler定理: 若(gcd(a, n)=1)(a^n = 1 (mod n))
意义:当(b)很大时,(a^b) = $a^{ (bmodn) }$ ((mod n)),让指数一直比较小

裴蜀定理:设(gcd(a,b)=d),一定存在整数(x,y),使得(ax+by=d) 。拓展GCD是求特解的过程。

int ex_gcd(int a, int b, int &x, int & y)
	   {if (b==0){ x = 1; y = 0; return a; }
        else {int r =ex_gcd(b, a%b, x, y);
                 int t = x; x = y; y = t – a/b*y;
                 return r; 
                }
       }

P1516 青蛙的约会

设总共跳(T)次可以相遇,则有:(A)的坐标(X+MT)(B)的坐标(Y+NT)相遇的充要条件:(X+MT-Y-NT=PL ( p是整数)) ,变形为((N-M)*T+LP=X-Y(L>0)),利用扩展欧几里德原理,求出最小的(T)即可。

(a1_{x1}+a2_{x2}+…+an_{xn}=N),有整数解的充分必要条件是((a1,a2,…,an)|N)

中国剩余定理

(a≡a1 (mod n1))
(a≡a2 (mod n2))
……………
(a≡ak (mod nk))

(a=(a1*c1+a2*c2+…+ak*ck) mod (n))…中国剩余定理
其中(n= n1*n2*…*nk)(ci=mi*(mi-1 mod ni))(mi=n/ni)

int remainder()//求同余方程组a
{int i,j,n=1,m,d,x,y;
 for (i=1;i<=k;i++) n*=n[i];
 a=0;
 for (i=1;i<=k;i++)//将同余方程组转化为对应的多项式求值
    {m=n/n[i];//求mi
      d=ex_gcd(n[i],m,x,y);//通过欧几里得扩展形式求y=mi-1
      a=(a+y*m*a[i])%n//累加a的值
    }
 if (a>0) return a;
 else return a+n;
}

炸 裂

容斥原理

错排问题

(n)个物品和(n)个盒子,编号都是从(1)(n)。现在要把每个物品放进一个盒子,每个盒子刚好放一个物品,并且(i)号物品不能放进(i)号盒子。求方案数模1000000007。
(n<=100000)

(n!)-(C_n^1*(n-1)!+C_n^2*(n-2)!-......+...)

阶乘,组合数都可以预处理(逆元方法(O(1))求组合数)

隔板法

(m)个未知数(x_1,x_2,……,x_m)。满足(x_1+x_2+x_3....+x_m=k) (0<=xi<=n)。求方程解的个数。(1<=n,m<=100000)(0<=k<=100000)

相当于有(k-1)个空,插进去(m-1)个板,答案即为(C_{k-1}^{m-1})

拓展:(xi>=n)

做法:(k)减去(m*n)即可转化为原题

概率与期望

如果一个随机事件发生的概率是(p),那么重复做这个实验,期望做多少次才能第一次发生该事件?

(1*p+2*(1-p)*p+3*(1-p)^2*p+4*(1-p)^3*p+……=1/p)

收集邮票

???????????????????????????????????

小左的GCD

似乎可做,求(1≤x,y≤N)(gcd(x,y))为素数的数对((x,y))的个数,就相当于是在(1<=x,y<=n/i)中找互素对,用欧拉函数可以(O(n))求解。

原文地址:https://www.cnblogs.com/57xmz/p/13763257.html