【AtCoder】 ARC 102

C-Triangular Relationship

发现要么全部是(K)的倍数,要么全部是模(K)(K/2,(K=2n))

#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"
"
#define dbg3(x) cerr<<#x<<"
"
using namespace std;
#define reg register
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
ll N,K,num;ll p3(ll x){return x*x*x;}
int main()
{
	N=read();K=read();
	num=p3(N/K);
	if(K%2==0) num+=p3(N/K+((N%K)>=(K/2)));
	printf("%lld
",num);
}



D-All Your Paths are Different Lengths

(L=2^{a_1}+2^{a_2}+...+2^{a_n},a_1<a_2<...<a_n)

建立(n)个中转点,每个点(i)向下一个点连接(0)(2^{i-1})的边

对于(a_i,i<n),第(a_i+1)个点在向最后一个点连(sum_{j=i+1}2^{a_j})的边

#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"
"
#define dbg3(x) cerr<<#x<<"
"
using namespace std;
#define reg register
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
int L,a[25],cnt;
int main()
{
	int L=read();
	reg int i,j,N=0,M=0;
	for(i=0;i<=20;++i)if(L>>i&1)a[++cnt]=i-1,++M;
	N=a[cnt]+2;M=M+N*2-3;
	printf("%d %d
",N,M);
	a[0]=-1;
	for(i=1;i<=cnt;++i)
	{
		for(j=a[i-1];j<a[i];++j)
			printf("%d %d %d
",j+2,j+3,0),
			printf("%d %d %d
",j+2,j+3,(1<<(j+1)));
		if(i==cnt) break;
		printf("%d %d %d
",a[i]+2,N,L-(1<<a[i]+1));
		L-=1<<a[i]+1;
	}
	return 0;
}



E-Stop. Otherwise

比较简单的计数问题,一个限制相当于有两个数只能选择其中的一个

枚举一下选了多少个这样有限制的组,组合数算一下每个数要多少个

#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"
"
#define dbg3(x) cerr<<#x<<"
"
using namespace std;
#define reg register
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
const int Mod=998244353,MN=4004;
int Mul(int x,int y){return (1ll*x*y)%Mod;}
int Add(int x,int y){return (x+y)%Mod;}
int fac[MN],inv[MN],p2[MN];
int C(int i,int j)
{
	if(i<0||j<0||i<j)return 0;
	return Mul(fac[i],Mul(inv[j],inv[i-j]));
}
int F(int i,int j){return C(i+j-1,j-1);}
int sol(int N,int pr,int nm)
{
	reg int i,j=min(N,pr);int r=0;
	for(i=0;i<=j;++i)r=Add(r,Mul(p2[i],Mul(C(pr,i),F(N-i,nm-pr+i))));
	return r;
}
int main()
{
	int N,K;reg int i,Ma;
	K=read();N=read();Ma=max(K,N);
	for(fac[0]=i=1;i<=Ma*2;++i)fac[i]=Mul(fac[i-1],i);
	for(inv[0]=inv[1]=1,i=2;i<=Ma*2;++i) inv[i]=Mul(inv[Mod%i],(Mod-Mod/i));
	for(i=2;i<=Ma*2;++i) inv[i]=Mul(inv[i-1],inv[i]);
	for(p2[0]=i=1;i<=Ma*2;++i) p2[i]=Mul(p2[i-1],2);
	for(i=2;i<=K*2;++i)
	{
		int ans=0,pr=i/2-max(i-K,1)+1;
		if(i%2==0) ans=Add(ans,sol(N-1,pr-1,K-pr));
		ans=Add(ans,sol(N,pr-(i%2==0),K-pr));
		printf("%d
",ans);
	}
	return 0;
}



F-Revenge of BBuBBBlesort

考虑逆操作的过程

发现(i-1,i,i+1)一旦交换过,(i)这个点就不会变了

最后,每个有变化的极大区间([i,j])一定满足

  1. (i,i+2,i+4,...j)的位置变化
  2. (i+1,i+3,i+5,...j-1)的位置不变

我们找到这样一个区间,又因为它无法与周围的其它的数交换,所以这个区间的值的集合应该恰好等于这个区间的每个位置下标的集合

考虑怎样才能移动为有序

首先,如果将一个数向右移动,那么它无法再向左移动,因为与它相邻的数是固定的,所以无法往回走

所以,一个数能朝着它的目标位置方向做单向运动

朝同一个方向运动的数单调递增,否则超越的那一步,前数朝反方向运动

相当于(a[i]<i)(a[i]>i)的点的(a[i])值分别单调递增

#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"
"
#define dbg3(x) cerr<<#x<<"
"
using namespace std;
#define reg register
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
const int MN=300005;
int a[MN],N;
void No(){puts("No");exit(0);}
void Yes(){puts("Yes");exit(0);}
void chk(int l,int r)
{
	reg int i,_1=0,_2=0;
	for(i=l+1;i<=r-1;i+=2)if(a[i]!=i)No();
	for(i=l;i<=r;i+=2)if(a[i]==i)No();
	for(i=l;i<=r;i+=2)
		if(i<a[i]){if(_1>a[i])No();_1=a[i];}
		else{if(_2>a[i])No();_2=a[i];}
}
main()
{
	N=read();reg int i;
	for(i=1;i<=N;++i) a[i]=read();
	int l=1,r;
	while(a[l]==l&&l<N)++l;
	while(1)
	{
		if(a[l]==l)Yes();
		if(l+2>N)No();r=l+2;
		int Mi=min(a[l],a[r]),Ma=max(a[l],a[r]);
		while((r!=Ma||l!=Mi)&&r<=N)r+=2,Mi=min(Mi,a[r]),Ma=max(Ma,a[r]);
		if(r>N)No();chk(l,r);
		l=r+1;while(a[l]==l&&l<N)++l;
		if(l>N)break;
	}
	Yes();
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

原文地址:https://www.cnblogs.com/PaperCloud/p/11374684.html