AtCoder Beginner Contest 171 总结

比上次多做了一道,但排名退了600,确实题比较水......

ABCDE几乎都算水题,C是一个类似秦九韶算法的东西,在26进制下搞一下即可,第一波搞忘减去余数还WA了......D利用“同一个数跟自己异或偶数次为0”的性质也很容易整出来,说一下F这道计数题。

题意很简单,问在一个给定的长为m的原字符串的基础上插入(可以插在串头和串尾)n个新字符能得到多少种新串,要做到不重复计数有一定难度。

最直接的思路就是n+m个位置上选m个位置放入原字符串的字符然后剩下的随便填,但很容易发现这么算会算重,比如aabbaabb是等价的但是会算两次。

于是考虑如何去重,我们让在串头插入的若干个元素随便填,然后让中间插入的元素,比如在第i个原字符之后插入的字符,不与第i个字符相同,这样做的原因是:如果能插入相同字符,那么得到的串一定可以通过调整之前插入的字符得到。比如aaaaabab等价于aaaaabababcbdbsbd等价于abcbdbsbd。所以在枚举中间和串尾插入的字符时只有25种选择而非26(开头插入的字符的选法为26)。所以,在新串的n+m个位置上,枚举一下开头插入的字符个数i(0<=i<=n),有26的i次方种选法,(然后将第一个原字符紧接着放入第i+1位)再乘上剩下m-1个原字符在n+m-i-1个位置上选位置的选法(组合数计算),再乘上剩下中间和串尾的待定字符的选法(25的n-i次方)。

ans=\sum_{i=0}^{n}26^{i}*C_{n+m-i-1}^{m-1}*25^{n-i}

求组合数时线性递推预处理一下阶乘和阶乘逆元即可。

P.S. 上述去重的过程也说明了答案只跟原串的长度有关,跟原串的字符无关,比如对于同一个n,"aaa"和"abc"的答案是一样的。官方题解说这一点很intuitive,可能是我菜了......并不觉得这很明显QAQ...

 

A题

#include
#include
#include
#include
using namespace std;

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

int main() {
	char x;
	scanf("%c",&x);
	if (x>='a'&&x<='z') puts("a");
	else puts("A");
	return 0;
}

B题

#include
#include
#include
#include
using namespace std;
const int N=1e3+4;
inline int read() {
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*f;
}
int n,m,sum;
int a[N];
int main() {
//	freopen("in.txt","r",stdin);
	n=read(),m=read();
	for (register int i=1;i<=n;++i) a[i]=read();
	sort(a+1,a+n+1);
	for (register int i=1;i<=m;++i) sum+=a[i];
	printf("%d\n",sum);
	return 0;
}

C题

#include
#include
#include
#include
using namespace std;
typedef long long ll;
inline int read() {
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*f;
}
ll x;
char sta[104];
int tot;
int main() {
//	freopen("in.txt","r",stdin);
	cin>>x;
	while (x) {
		ll cur=x%26;
		if (cur==0) cur=26;
		x-=cur;
		sta[tot++]='a'+cur-1;
		x/=26;
	}
	for (int i=tot-1;~i;--i)
		printf("%c",sta[i]);
	return 0;
}

D题

#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=1e5+4;
int n,m;
int a[N],b[N];
int cnt[N];
ll sum;
inline int read() {
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*f;
}
int main() {
//	freopen("in.txt","r",stdin);
	n=read();
	for (register int i=1;i<=n;++i) {
		a[i]=read();
		++cnt[a[i]];
		sum+=a[i];
	}
	m=read();
	for (register int i=0;i

E题

#include
#include
#include
#include
using namespace std;
const int N=2e5+4;
inline int read() {
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*f;
}
int n;
int a[N];
int sum;
int main() {
	freopen("in.txt","r",stdin);
	n=read();
	for (register int i=1;i<=n;++i) {
		a[i]=read();
		sum^=a[i];
	}
	for (register int i=1;i<=n;++i) {
		printf("%d ",sum^a[i]);
	}
	return 0;
}

F题

#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=1e6+4;
const ll MOD=1e9+7;
inline int read() {
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*f;
}
ll fac[N<<1]={1,1};
ll inv[N]={1,1};
int n,m;
char s[N];
inline ll fpow(ll a,int b) {
	ll ret=1;
	while (b) {
		if (b&1) ret=ret*a%MOD;
		b>>=1,a=a*a%MOD;
	}
	return ret;
}
inline ll C(int x,int y) {
	ll ans=fac[x];
	ans=ans*inv[y]%MOD;
	ans=ans*inv[x-y]%MOD;
	return ans;
}
int main() {
//	freopen("in.txt","r",stdin);
	for (register int i=1;i<(N<<1);++i) fac[i]=fac[i-1]*i%MOD;
	inv[N-1]=fpow(fac[N-1],MOD-2);
	for(int i=N-2;~i;--i)
	   inv[i]=inv[i+1]*(i+1)%MOD;
	n=read();
	scanf("%s",s);
	m=strlen(s);
	ll ans=0;
	for (register int i=0;i<=n;++i) {
		ll c=fpow(26,i)*fpow(25,n-i)%MOD;
		(ans+=c*C(n+m-i-1,m-1)%MOD)%=MOD;
	}
	printf("%lld\n",ans);
	return 0;
}

 

你可能感兴趣的:(AtCoder总结)