牛客小bai月赛39——A憧憬、H终别、G冷静

A、憧憬

思路:

通过两个点 (x1,y1), (x2,y2) 确定一个向量(a,b) = (x1-x2, y1-y2)

判断两个向量 (a,b), (c,d) 是否平行
方法1:若 a*d = b*c,则两个向量平行。
方法2:向量看作过原点的直线,比较斜率。但是这个斜率不是直接纵横坐标相除,而是用pair存最简分数来表示:
如果两个向量的最简分数相同或者互为相反数(分子互为,分母互为),则斜率相同。 (再次安利 芬兰木棋 这道题!)

bool pd()
{
    
    
	PII k1,k2;
	int g=__gcd(abs(x),abs(y));
	k1={
    
    x/g,y/g};
	
	g=__gcd(abs(xx),abs(yy));
	k2={
    
    xx/g,yy/g};
	
	if(k1==k2||k2.first==-k1.first&&k2.second==-k1.second) return 1;
	return 0;
}

由此可以想到,也可用向量来判定两条线段是否平行。


H、终别

思路:

如果不考虑使用魔法的话,消灭n个怪兽所用的最小操作数是:
采用贪心策略,每次连续三个位置,先将第一位置怪兽血量变为0,再将第二位置变为0…

但是现在可以有两个相邻位置i,j可以直接消灭,也就是不用考虑。

所以将该问题划分为[1,i-1], [j+1,n]两个子问题。

可以遍历不用消灭的两个相邻位置。
如果每次遍历都一遍的话,复杂度为 O ( n 2 ) O(n^2) O(n2)
所以需要预处理出pre[i]:1~i 个怪兽需要的最小操作数,last[i]:i~n个怪兽需要的最小操作数。
ans = min(ans, pre[i-1] + last[i+2])

关键是要认识到两个点:

  1. 将一个区间全部变为0的操作数是固定的,贪心实现。
  2. 预处理的很妙!

Code:

const int N = 2000010, mod = 1e9 + 7;
int T, n, m, a[N], b[N];
ll pre[N],last[N];

int main(){
    
    
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
	
	for(int i=1;i<=n;i++)
	{
    
    
		pre[i]=pre[i-1];
		if(b[i]>0){
    
    
			pre[i]+=b[i];
			b[i+1]-=b[i];
			b[i+2]-=b[i];
		}
	}
	for(int i=1;i<=n;i++) b[i]=a[i];
	
	for(int i=n;i>=1;i--)
	{
    
    
		last[i]=last[i+1];
		if(b[i]>0){
    
    
			last[i]+=b[i];
			b[i-1]-=b[i];
			b[i-2]-=b[i];
		}
	}
	ll ans=1e18;
	for(int i=1;i<=n-1;i++)
	{
    
    
		ans=min(ans,pre[i-1]+last[i+2]);
	}
	cout<<ans;
	
	return 0;
}

G、冷静

思路:

每次询问给定 n 和 K,问 1 ~ n 中有多少数可以表示为大于等于 K 的质数的乘积。
由算数基本定理:
在这里插入图片描述
所以要计算出每个数的最小质因子,提前储存起来。

通常的方法是 埃式筛:
因为 埃式筛 每个数都是被其最小质因子筛掉的,所以复杂度O(n)。所以标记出每个数是由谁筛掉的就行了。

void Prim(int n)
{
    
    
	for(int i=2;i<=n;i++)
	{
    
    
		if(!f[i]) prim[++cnt]=i,ans[i]=i;
		
		for(int j=1;prim[j]<=n/i;j++)
		{
    
    
			f[prim[j]*i]=1;
			ans[prim[j]*i]=prim[j];
			
			if(i%prim[j]==0) break;
		}
	}
}

但是今天又想到一种方法:分解质因数 。还不确定对不对。
每个数都可以分解为若干个质数的乘积,所以找出第一个分解的质因数便是最小质因数。

void prim(int n)
{
    
    
	for(int i=2;i<=n/i;i++)
	{
    
    
		if(n%i==0){
    
    
			f[n]=i; return;
		}
	}
	f[n]=n;
}

之后便是判断一个区间中有多少个数的最小质因子不小于K,用 树状数组 或 线段树。


Guess you like

Origin blog.csdn.net/Mr_dimple/article/details/121186576