0
点赞
收藏
分享

微信扫一扫

第十九届浙大城市学院程序设计竞赛(F、L)

夕颜合欢落 2022-04-14 阅读 71
c++

F Sum of numerators(数论)

描述:
在这里插入图片描述
题目大意:

给出 n 和 k ,计算所给式子最简的所有分子和;

思路:

我们举一组例子:
n=10,k=2;

先不化简:

所有的分子是

12345678910

分母是 4;

先求一次和;

这时对所有的偶数除 2(奇数对和无影响)
偶数变为

12345
分母是 4/2=2
序列长度为10/2=5

减去因为化简而多出的贡献

再对偶数化简一次(分母还是2的倍数)

偶数变为

12
分母是 2/2=1
序列长度为5/2=2

减去因为化简而多出的贡献

这时虽然还有偶数,但是分母不为2的倍数,化到了最简;

从这个例子里我们就能找到规律,先求出不化简的总和,再根据 n 和 k的大小不断减去多算的贡献

代码:

#include<bits/stdc++.h>
using namespace std;
 
typedef unsigned long long ull;
typedef long long ll;
 
const ll maxx = 1e18;
const int N = 1e6+100;
const int p = 1e4;
const double eps = 1e-8;

ll n,k;
ll t;

int main()
{
	cin>>t;
	
	while(t--)
	{
		cin>>n>>k;
		
		ll sum=(n+1)*n/2;
		
		while(n>1&&k>0)
		{
			n/=2;
			k--;//分母每次除2对应k减1
			sum-=(n+1)*n/2;
		}
		
		cout<<sum<<endl;
	}
	
	
	return 0;
 } 

L Monster Tower(模拟)

在这里插入图片描述
大意:

打怪,给出怪物塔的总层数 n 和能达到的层数 k
当打死一层的怪会获得怪的能力值,本层消失,本层上边的层数减一,求通关的最小能力值

思路:
打怪的顺序是唯一的,所以维护一个有 k 个元素的小根堆,每次处理最小的元素,如果现有能力值大于怪的能力值,加上怪的能力值,否则更新初始值;

每遇到一个打不过的怪,最小可能初始值 = 怪的能力值-前面获得的能力值总和,用这个值去更新之前的 初始值,取其中大的;

#include<bits/stdc++.h>
using namespace std;
 
typedef unsigned long long ull;
typedef long long ll;
 
const ll maxx = 1e18;
const int N = 1e6+100;
const int p = 1e4;
const double eps = 1e-8;

ll t,n,k;

ll a[N];
priority_queue<ll,vector<int>,greater<int> >pmin;

ll sta,now;

int main()
{
	cin>>t;
	
	while(t--)
	{
		cin>>n>>k;
		
		sta=0;now=0;
		
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
		}
		
		for(int i=1;i<=n;i++)
		{
			if(pmin.empty()||pmin.size()<k) pmin.push(a[i]);//注意判空
			else
			{
				ll s=pmin.top();
				pmin.pop();
				
				if(now>=s)
				{
					now+=s;
				}//总能力值大于怪的能力值
				else
				{
					sta=max(sta,s-now);
					now+=s;
				}//更新初始值,注意更新方式
				
				pmin.push(a[i]);
			}
		}
		
		
		while(!pmin.empty())
		{
			ll s=pmin.top();
			pmin.pop();
				
			if(now>=s)
			{
				now+=s;
			}
			else
			{
				sta=max(sta,s-now);
				now+=s;
			}
		}
		
				
		cout<<sta<<endl;		
		
	}
		
	
	return 0;
}
举报

相关推荐

0 条评论