2021暑假集训Day 4

数论 背包 分块 数论?

A

Decription:

若数列A存在位置k,满足
①i<k,ai<ai+1
②i>=k,ai>ai+1
则称该数列为单峰数列
给出正整数n,求全排列n中存在多少个单峰数列

Input

给出1个正整数n

Output

单峰数列个数(对10^9+7取模)

Sample Input:

3

Sample Output:

4

Data Constraint

20%:n ≤ \leq 10
50%:n ≤ \leq 10^5
100%:2 ≤ \leq n ≤ \leq 10^18

思路:
数据这么大,明显是数论,是的,尝试着就来推一波,对于最大值n来说,他肯定就是那个峰值,那么我们试着看一下,峰值肯定是n,考虑n左右放哪些数,决定放哪些数以后,排列是固定的即n左边放的数单调递增,n右边放的数单调递减方案数为C(n-1,0)+C(n-1,1)+…+C(n-1,n-1)= 2 ( n − 1 ) 2^{(n-1)} 2(n1)
那么不就是一道水体了吗,快速幂取模走起。

#include<iostream>
#include<cstdio>
#define ll long long
#define mod 1000000007
using namespace std;
ll n;
ll ksm(ll x,ll y)
{
	ll res=1;
    while(y)
	{
	  if(y&1) res=(res%mod*x%mod)%mod;
	  x=(ll)(x*x)%mod,y>>=1; 
	}
	return res;	
}
int main()
{
    scanf("%lld",&n);
    n--;
    printf("%lld",ksm(2,n));
	return 0;
} 

B

Decription:

XJQ要做N件事,需要消耗它不同的精力,做完之后还会获得一定的信誉。对于每件事他可以选择做或不做,而且他还有可能真香一些事,真香之后这些事就不能再做了。对于每次真香,他都想知道以他的精力,最多可以获得多少信誉。

Input

第一行2个正整数n,m表示有n件事它开始拥有的精力
第n行,每行两个数,表示需要精力和可以获得的信誉
接下来n-1行一个数表示了他真香了哪件事
每次真香对下一次真香有影响

Output

第一行为开始时可以获得的最多信誉
接下来n-1行表示他真香了某件事后可以获得的最多信誉

Sample Input:

5 20
7 1
1 1
13 1
1 9
1 16
1
4
2
3

Sample Output:

27
27
18
17
16

Data Constraint

1~3:n,m ≤ \leq 100
3~5:n ≤ \leq 1000,m ≤ \leq 5000
6~10:n ≤ \leq 4000,m ≤ \leq 10000
其他数均为正整数,且不大于10000

思路:
看得出来是个01背包,倒过来dp不就完事了?秒了吧?

#include<iostream>
#include<cstdio>
#define M 10000
#define N 4000 
using namespace std;
int n,m,dp[M+11],f[N+11],val[N+11],ban[N+11],maxn,ans[N+11];
bool bo[N+11];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&f[i],&val[i]);
    for(int i=1;i<=n-1;i++) scanf("%d",&ban[i]),bo[ban[i]]=1;
    for(int i=1;i<=n;i++) 
    {
    	if(!bo[i])
    	{
    		ban[n]=i;
    		break;
		}
	}
    for(int i=n;i>=1;i--)
    {
    	maxn=0;
    	for(int j=m;j>=f[ban[i]];j--)
    		dp[j]=max(dp[j-f[ban[i]]]+val[ban[i]],dp[j]),maxn=max(dp[j],maxn);
    	ans[i]=maxn;
	}
	for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
	return 0; 
} 

C

Decription:

给定一个长度为n的数列a,有m次操作,操作分两种:
1 给出[l,r],表示将此区间的数轮转一次,即变成 a r a_r ar, a l a_l al a r − 1 a_{r-1} ar1
2 给出[l,r]和k,询问此区间内 a i a_i ai==k的个数

Input

第一行给出n,m
第二行给出序列a
接下来m行给出m次操作

Output

对于每个询问,给出一行表示答案

Sample Input:

7 6
1 2 2 3 2 1 3
2 3 6 2
1 1 6
2 2 4 1
1 3 6
2 6 7 3
2 3 5 2

Sample Output:

2
1
2
3

Data Constraint

1~3:n,m ≤ \leq 100
3~5:n ≤ \leq 1000,m ≤ \leq 5000
6~10:n ≤ \leq 4000,m ≤ \leq 10000
其他数均为正整数,且不大于10000

思路:
分块,我的分块写炸了,总的复杂度为O(n n \sqrt{n} n )
转载了disPlayLzy_的博客代码,大家先看一看,小编会后续更改的,再次感谢disPlayLzy_。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define N 100005

using namespace std;

int A[335][N], Belong[N], C[355], D[355], num, cnt, n, m;

void read(int &x)
{
	int f = 1; x = 0; char s = getchar();
	while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
	while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
	x = x * f;
}

deque <int> Q[N];
 
int main()
{
//	freopen("queue.in", "r", stdin);
//	freopen("queue.out", "w", stdout);
	read(n); read(m);
	num = sqrt(n);
	for (int i = 1; i <= n; i++) 
	{
		 int x; read(x); 
		 if (i  > num * cnt) ++cnt;
		 Q[cnt].push_back(x);
		 Belong[i] = cnt, ++A[cnt][x];
	}
	while (m--)
	{
		int opt; read(opt);
		if (opt == 1)
		 {
			int l, r; read(l); read(r);
			if (Belong[l] == Belong[r])
			{
				int G = Belong[l];
				l = l % num; if (l == 0) l = num;
				r = r % num; if (r == 0) r = num;
			    for (int i = 1; i < l; i++) //把 1~L 取出来 
				    C[i] = Q[G].front(), Q[G].pop_front();
			    for (int i = 1; i <= num - r; i++)
			        D[i] = Q[G].back(), Q[G].pop_back();
			        
			    int x = Q[G].back(); Q[G].pop_back(); Q[G].push_front(x); 
				for (int i = l - 1; i >= 1; i--) Q[G].push_front(C[i]);
			    for (int i = 1; i <= num - r; i++) Q[G].push_back(D[(num - r) - i + 1]);
			}
			else 
			{
				int G = Belong[l], k = l; while (Belong[k + 1] == G) ++k;
			    int len1 = k - l + 1;
			    for (int i = 1; i <= len1; i++)
				    C[len1 - i + 1] = Q[G].back(), Q[G].pop_back(), A[G][C[len1 - i + 1]]--; 
				    
			    int F = Belong[r], h = r; while (Belong[h - 1] == F) --h;
			    int len2 = r - h + 1; 
			    for (int i = 1; i <= len2; i++)
			        D[i] = Q[F].front(), Q[F].pop_front(), A[F][D[i]]--;
			    
			    Q[G].push_back(D[len2]), A[G][D[len2]]++;
			    for (int i = 1; i < len1; i++) Q[G].push_back(C[i]), A[G][C[i]]++;
	            
	            for (int i = len2 - 1; i >= 1; i--) Q[F].push_front(D[i]), A[F][D[i]]++; 
				int x = Q[F - 1].back(); if (F == G + 1) x = C[len1];
				Q[F].push_front(x), A[F][x]++;
	            
	            int last = C[len1];
	            for (int i = G + 1; i <= F - 1; i++)
	            {
				    Q[i].push_front(last); A[i][last]++;
					last = Q[i].back(); Q[i].pop_back();
					A[i][last]--; 	    
			    }
			}
		} 
		else 
		{
			int l, r, K, orz = 0; read(l); read(r); read(K);
			if (Belong[l] == Belong[r])
			{
				int G = Belong[l];
				l = l % num; if (l == 0) l = num;
				r = r % num; if (r == 0) r = num;
			    for (int i = 1; i < l; i++) 
				    C[i] = Q[G].front(), Q[G].pop_front();
			    for (int i = 1; i <= num - r; i++)
			        D[i] = Q[G].back(), Q[G].pop_back();
			        
				for (int i = l - 1; i >= 1; i--) 
				{
					if (C[i] == K) ++orz;
				    Q[G].push_front(C[i]);
				}
			    for (int i = 1; i <= num - r; i++) 
				{
				    if (D[(num - r) - i + 1] == K) ++orz;
					Q[G].push_back(D[(num - r) - i + 1]);
			    }
			    orz = A[G][K] - orz;
			}
			else 
			{
				int G = Belong[l], k = l; while (Belong[k + 1] == G) ++k;
			    int len1 = k - l + 1;
			    for (int i = 1; i <= len1; i++) C[len1 - i + 1] = Q[G].back(), Q[G].pop_back(); 
				for (int i = 1; i <= len1; i++) 
				{
				    if (C[i] == K) ++orz;
					Q[G].push_back(C[i]);
				}
				
			    int F = Belong[r], h = r; while (Belong[h - 1] == F) --h;
			    int len2 = r - h + 1; 
			    for (int i = 1; i <= len2; i++) D[i] = Q[F].front(), Q[F].pop_front();  
	            for (int i = len2; i >= 1; i--) 
				{
				    if (D[i] == K) ++orz;
					Q[F].push_front(D[i]); 
			    }
	            for (int i = G + 1; i <= F - 1; i++) orz += A[i][K];
			} 
			printf("%d\n", orz);
		}
	}
	return 0;
}

D 后续更新

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值