HPU personal training 11月18日

传送门

A题

https://blog.csdn.net/qq_45328552/article/details/103207775

B题

题意:从n个数中选k个数,有多少种选法。

思路:规律,有n-(k-1)中。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

int main()
{
    int n,k;
    cin>>n>>k;
	cout<<n-(k-1)<<endl; 

    return 0;
}

C题

题意:有n个数从0~n,这n个数重新排列组合成为{p1,p2...pn},让这个新的组合分别对应{0,1,2...n}取余的值相加,问最大值是多少?

思路:例如1,2,3,4,5,6  新的排列的应该为2,3,4,5,6,1  把所有数往前移动一位,第一位移到最后面,这样能使取余结果最大化。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;

int main()
{
//	freopen("input.txt","r",stdin);
	
	ll n;
	cin>>n;
	ll ans=0;
	for(ll i=1;i<n;i++) ans+=i;
	cout<<ans<<endl;

	return 0;
}

E题

题意:给你n个点分别是第1~n个点距离Di,用这n个点组成一个树,问能组成多少个(即求有多少个满足条件的同分异构体的树)。需要注意的是,这n个点组成的树是n-1条边组成的无向图,而0≤DiN−1,故可知每条边的权值为1。

思路:在纸上模拟简单树可知,设ans=1,同分异构体的数目是,第一层节点数目的第二层节点数目次方(ans*=a1^a2),再乘以第二层数目的第三层数目次方(ans*=a2^a3)...直到乘到最后一层。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>
#include <map>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;
const ll mod= 998244353;

ll a[maxn];

ll ksm(ll a,ll n)
{
	ll res=1;
	while(n)
	{
		if(n&1) res=res*a%mod;
		a=a*a%mod;
		n>>=1;
	}
	
	return res%mod;
}

int main()
{
	ll n;
	cin>>n;
	ll flag1=0;//用来表示不能形成树的情况 
	ll Max=0;
	for(int i=0;i<n;i++)
	{
		ll x;
		cin>>x;
		if(i==0&&x!=0) flag1=1; 
		a[x]++;	
		Max=max(Max,x);
	} 
	if(a[0]!=1) flag1=1;
	for(int i=0;i<=Max;i++) if(a[i]==0) flag1=1;
	ll ans=1;
	for(int i=0;i<Max;i++) ans=ans*ksm(a[i],a[i+1])%mod;
	if(flag1) ans=0;
	cout<<ans%mod<<endl;
    
    return 0;
}

F题

思路:求所有数的最大公约数。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

int a[maxn];

int main()
{
//    freopen("input.txt","r",stdin);
    
    int n;
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    sort(a,a+n);
    int temp=a[0];
    for(int i=1;i<n;i++) temp=__gcd(temp,a[i]);
    cout<<temp<<endl;
    
    return 0;
}

G题

算法:贪心。

题意:给你n个需要购买的item的价钱,k个折扣券,每个折扣券能打5折。(最简洁明了题意)

思路:每个折扣券能打5折,你选择用在啥上面,肯定是最贵的上面啊!重复更新,每次给最贵的使用折扣券,即sum/2。

之前想的是用sort排序,但是sort排序的时间复杂度是O(n*log n),这是大于线性但小于平方的复杂度,这样整个程序的复杂度就大于n*m了,肯定会超时。

优先队列的时间复杂度是O(n),小于sort排序的时间复杂度,所以能过。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

priority_queue<int> q;

int main()
{
//    freopen("input.txt","r",stdin);
    
    ll n,m;
    cin>>n>>m;
    for(ll i=0;i<n;i++) 
    {
    	int x;
    	cin>>x;
    	q.push(x);
	}
    for(ll i=0;i<m;i++)
    {
    	int temp=q.top();
    	q.pop();
    	temp/=2;
    	q.push(temp);
	}
	ll ans=0;
	for(ll i=0;i<n;i++) 
	{
		int temp=q.top();
		q.pop();
		ans+=temp;
	}
	cout<<ans<<endl; 

    return 0;
}


其实这一题我之前就像放弃了,但是慢慢看题、理解题意,把复杂的题意简单化,慢慢有了思路,出错了,想出了优先队列的解法,没有怕麻烦,又去尝试,没想到竟然成功了。

也让我知道,只要坚持,惊喜就会到来,把题意简单化,思路简单化,换个角度,死磕它,我也能做更多的题。

H题

把n个人的起始k值先全部减去Q,然后遍历给出的Q个数,遍历到的那个人生命值+1,最后如果谁的生命值大于1,输出yes,否则输出no。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

int a[maxn];

int main()
{
//    freopen("input.txt","r",stdin);
    
    int n,k,q;
    cin>>n>>k>>q;
    for(int i=0;i<n;i++) a[i]=k-q;
    for(int i=0;i<q;i++)
    {
    	int x;
    	cin>>x;
    	a[x-1]++;
	}
	for(int i=0;i<n;i++) 
	{
		if(a[i]>0) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
    
    return 0;
}

I题

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

int a[maxn];

int main()
{
//	freopen("input.txt","r",stdin);
	
	ll n;
	cin>>n;
	int ans=0,res=0;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<n;i++)
	{
		if(a[i]<=a[i-1]) ans++;
		else ans=0;
		res=max(res,ans);
	}
	cout<<res<<endl;

	return 0;
}

M题

题意:给你n个字符串,这n个字符串可以任意排列最后组合到一起,问其中“AB”字符串最多有多少。

思路:只单纯的去想有多少个子串是徒劳的,关键是找到普遍规律。每个字符串中可构成AB子串的有AB,...A,B...,B...A。找到这四种元素的个数就能想办法求出答案。AB可以求出,关键是另外三种元素组成AB子串的个数,我是先把B...A的问题解决掉,如果有n个B...A,则能表示成n-1个AB和一个B...A,然后和另外两个元素结合求一下就行了。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

int a[maxn];

int main()
{
//	freopen("input.txt","r",stdin);
	
	ll n;
	cin>>n;
	int ans=0,res=0;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<n;i++)
	{
		if(a[i]<=a[i-1]) ans++;
		else ans=0;
		res=max(res,ans);
	}
	cout<<res<<endl;

	return 0;
}

//有n个仓库,m个工人,任何 
原创文章 99 获赞 15 访问量 7335

猜你喜欢

转载自blog.csdn.net/qq_45328552/article/details/103129699
今日推荐