2019.10.31日CSP-S备赛

T1

次芝麻
【题目描述】
小K和小X都是小次货。
身为小次货,最重要的事情当然是次啦,所有他们正在纠结如何分芝麻次。
一开始,小K有n个芝麻,小X有m个芝麻。
因为他们都想次更多芝麻,所以每次手中芝麻较少的人就会拿走另一个人的芝麻,使得自己的芝麻变成原来的2倍那么多。如果两个人芝麻一样多,那么小K会拿小X的芝麻使得他的芝麻变成原来的2倍。
经过K次这样的行动之后,小K和小X都累了,所以他们准备开始次芝麻了。
身在一旁的小Z想知道,小K和小X中次的较少的那个人次了多少芝麻呢?
【输入格式】
一行三个整数n,m,k.
【输出格式】
一行一个整数,表示答案
【样例输入】
5 5 3
【样例输出】
0
【样例解释】
第一次行动时,小K拿走小X的芝麻5个,行动后小K有10个芝麻,小X有0个芝麻。
第二次和第三次行动都是小X拿走小K的芝麻,但是因为他一开始没有芝麻,所以不能拿走小K的芝麻。
最终小K有10个芝麻,小X有0个芝麻,次的较少的人是小X,次了0个芝麻。
**

T2

喝喝喝
【问题描述】
奥利维尔和雪拉扎德在喝酒。
两人连喝18瓶后,奥利维尔终于倒下了。
奥利维尔服用了教会研究的醒酒药后,因为服用太多产生了副作用,第二天睡不着了。
他只好用数数的方式度过无聊的时光,不过他毕竟是皇子,是不会数羊的。他会数数解决下面这个问题:
他先写下一个长度为n的数组a,一对数组中的数{ , }被称为坏对,当且仅当x<y且 mod =K。那么有多少个连续子数组不包含坏对呢?
【输入格式】
第一行包含两个整数,n和K
第二行包含n个整数,表示数组a。
【输出格式】
输出一行包含答案。
【样例输入】
3 2
5 3 1
【样例输出】
4
【样例解释】
{5,3}是这个数组中唯一一个坏对。
**

T3

长寿花
【题目描述】
庭院里有一棵古树。
圣诞节到了,我想给古树做点装饰,给他一个惊喜。
他会不会喜欢呢?
这棵树可以被分为n层,第i层有个放置装饰品的位置。有m种颜色的装饰品可供选择。
为了能让他喜欢,我想让装饰品满足以下条件。
在同一层两个相邻的饰品不能有同一种颜色:
相邻两层的颜色集合不能相同(这里颜色集合是指这一层所有出现的颜色去重后的集合,也就是每个颜色只在集合内最多出现一次)。
我想知道,有多少种不同的方法能让他满意呢?由于方法数可能很多,请告诉我模p之后的答案。
谢谢你。
【输入格式】
第一行三个整数,n,m,p
第二行n个整数,第i个整数表示
【输出格式】
一行一个整数,表示答案。
【样例输入】
3 2 1000
3 1 2
【样例输出】
8
【样例解释】
如下几种方法满足条件:

  1. 121|1|12
  2. 121|1|21
  3. 121|2|12
  4. 121|2|21
  5. 212|1|12
  6. 212|1|21
  7. 212|2|12
  8. 212|2|21
    **

题解

在这里插入图片描述



标程

T1

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
LL qpow(LL x,LL n,LL MOD)
{
	LL con=1,p=x;
	while(n)
	{
		if(n&1) con=(con*p)%MOD;
		p=(p*p)%MOD;
		n>>=1;
	}
	return con;
}
int n,m,k;
LL MOD;
int main()
{

	scanf("%d%d%d",&n,&m,&k);
	MOD=n+m;
	LL x=((LL)n*qpow(2LL,k,MOD))%MOD;
	printf("%lld\n",min(x,MOD-x));
}

T2

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=100000;
const int MAXN=100010;
int n,k,K,a[MAXN],c[MAXN],sum[MAXN],L;
vector<int> v[MAXN];
LL ans;
int main()
{
	freopen("drink.in","r",stdin);
	freopen("drink.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	K=(int)sqrt(N);
	for(int i=k+1;i<=K;i++)
		for(int j=k;j<=N;j+=i)
			v[j].push_back(i);
	c[a[1]]++;
	for(int i=0;i<v[a[1]].size();i++) sum[v[a[1]][i]]++;
	ans++,L++;
	for(int i=2;i<=n;i++)
	{
		if(a[i]>K&&a[i]>k)
		{
			while(true)
			{
				int x=0;
				for(int j=k;j<=N;j+=a[i]) x+=c[j];
				if(x==0) break;
				c[a[L]]--;
				for(int j=0;j<v[a[L]].size();j++) sum[v[a[L]][j]]--;
				L++;
			}
			ans+=(LL)(i-L+1);
		}
		else if(a[i]>k)
		{
			while(true)
			{
				int x=sum[a[i]];
				if(x==0) break;
				c[a[L]]--;
				for(int j=0;j<v[a[L]].size();j++) sum[v[a[L]][j]]--;
				L++;
			}
			ans+=(LL)(i-L+1);
		}
		else ans+=(LL)(i-L+1);
		c[a[i]]++;
		for(int j=0;j<v[a[i]].size();j++) sum[v[a[i]][j]]++;
	}
	printf("%lld\n",ans);
	return 0;
}

T3

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const int MAXN=1000010;
int n,m,MOD,l[MAXN];
int f[5010][5010];
LL fac[5010],P[5010],ans;
vector<LL> d[MAXN];
int main()
{
	freopen("kalanchoe.in","r",stdin);
	freopen("kalanchoe.out","w",stdout);
	scanf("%d%d%d",&n,&m,&MOD);
	for(int i=1;i<=n;i++) scanf("%d",&l[i]);
	P[1]=m;
	for(int i=2;i<=min(m,5000);i++) P[i]=(P[i-1]*(m-i+1))%MOD;
	fac[0]=1;
	for(int i=1;i<=5000;i++) fac[i]=(fac[i-1]*i)%MOD;
	f[1][1]=1;
	for(int i=2;i<=5000;i++)
		for(int j=1;j<=5000;j++)
			f[i][j]=((LL)f[i-1][j-1]+(LL)f[i-1][j]*(j-1))%MOD;
	for(int i=1;i<=n;i++) d[i].resize(l[i]+1);
	for(int i=1;i<=l[1];i++) d[1][i]=(P[i]*(LL)f[l[1]][i])%MOD;
	for(int i=2;i<=n;i++)
	{
		LL Sum=0;
		for(int j=1;j<=l[i-1];j++) Sum=(Sum+d[i-1][j])%MOD;
		for(int j=1;j<=l[i];j++)
		{
			d[i][j]=((P[j]*(LL)f[l[i]][j])%MOD*Sum)%MOD;
			if(j<=l[i-1]) d[i][j]=(d[i][j]-((d[i-1][j]*(LL)f[l[i]][j])%MOD*fac[j])%MOD+MOD)%MOD;
		}
	}
	for(int i=1;i<=l[n];i++) ans=(ans+d[n][i])%MOD;
	printf("%lld\n",ans);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值