佳木斯集训Day3考试

吐槽一下今天的考试 前两道题打的正解没有打暴力的分高…要不就rk1了…
佳木斯集训Day3考试_第1张图片

字符串

题目描述
给定两个长度相等的字符串,保证字符串之间差奇数个,请求出排中间的字符串是多少
输入
第一行,一个正整数n表示字符串长度
接下来2行,表示两个长度为n的字符串
输出
一行,表示位于中间的字符串
样例输入
2
az
bf
样例输出
bc

将a设为0,b设为1,c设为2…z设为25
将两个字符串在26进制下相加除以2就好了额
注意加法进位后除以2要退一位 不然你就会丢掉60分

#include
int n,a[200010],b[200010],c[200020];
char ch;
int main()
{
     
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
     
		ch=getchar();
		while(ch<'a'||ch>'z')ch=getchar();
		a[n-i+1]=ch-'a';
	}
	for(int i=1;i<=n;i++)
	{
     
		ch=getchar();
		while(ch<'a'||ch>'z')ch=getchar();
		b[n-i+1]=ch-'a';
	}
	for(int i=1;i<=n;i++)
	{
     
		c[i]+=a[i]+b[i];
		c[i+1]+=(c[i]/26);
		c[i]%=26;
	}
	bool bl=0;
	if(c[n+1]>0)
	{
     
		n++;
		bl=1;
	}
	for(int i=n;i;i--)
	{
     
		c[i-1]+=(c[i]%2*26);
		c[i]/=2;
	}
	if(bl)n--;
	for(int i=n;i;i--)putchar(c[i]+'a');
	putchar('\n');
}

gcd

题目描述
给定n个数,问最少选几个数,使他们的gcd为1
输入
第一行一个正整数n
第二行,共n个数表示ai
输出
输出 1 行,表示答案,若不存在则输出-1
样例输入
3
10 6 15
样例输出
3
数据范围
对于40% 保证 n<=20
对于另外20% 保证 n<=1000,ai<=2000
对于100% 保证 1<=n,ai<=300000

首先 如果选了一个数而这个数并没有让gcd少质因子,那么这个数没有卵用
而最大只能有 2 × 3 × 5 × 7 × 11 × 13 × 17 = 510510 > 300000 2×3×5×7×11×13×17=510510>300000 2×3×5×7×11×13×17=510510>300000 7个质因子 所以答案一定小于等于7
所以我们可以输入时判一下总的gcd是否输出-1 然后在1-7里rand
数论题的基本我自己思路:遇事不决,枚举 g c d gcd gcd
f ( i ) f(i) f(i)为在当前选 k k k个数时 这 k k k个数的公约数为i的总方案
g ( i ) g(i) g(i)为在当前选 k k k个数时 这 k k k个数的最大公约数为i的总方案
那么 g ( i ) = f ( i ) − ∑ j = 2 ⌊ n j ⌋ f ( i ∗ j ) g(i)=f(i)-\sum_{j=2}^{\left \lfloor \frac{n} {j} \right \rfloor}f(i*j) g(i)=f(i)j=2jnf(ij)
n n n 1 1 1 g ( i ) g(i) g(i) 最后如果 g ( 1 ) g(1) g(1)大于 0 0 0 k k k是一个合法的答案
所以你一定有问题了 f ( i ) f(i) f(i)怎么求? 好问题
f ( i ) f(i) f(i)为选出k个数公约数为i的总方案 我们需要预处理出数列中是 i i i的倍数的数 c n t ( i ) cnt(i) cnt(i)
显然 f ( i ) = ( c n t ( i ) k ) f(i)=\binom{cnt(i)}{k} f(i)=(kcnt(i))
所以我们需要预处理 出 1 − N 1-N 1N的阶乘逆元 m o d mod mod随便设一个大一点的素数就好了 设小你就跪了
时间复杂度为 O ( n ln ⁡ n ) O(n\ln n) O(nlnn)
代码如下

#include
#include
using namespace std;
typedef long long ll;
const int N=300010,mod=1000000009;
inline void read(int &x)
{
     
	int s=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9'){
     s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
	x=s;
}
ll inv[N],fac[N],facinv[N],f[N];
ll C(ll n, ll m){
     return !n?0:fac[n]*facinv[m]%mod*facinv[n-m]%mod;}
int n,x,cnt[N];
bool check(int l)
{
     
	memset(f,0,sizeof(f));
	for(int i=N-1;i;i--)
	{
     
		f[i]=C(cnt[i],l);
		if(f[i])for(int j=2;i*j<N;j++)f[i]=(f[i]-f[i*j]+mod)%mod;
	}
	return f[1];
}
int main()
{
     
	fac[0]=facinv[0]=inv[1]=fac[1]=facinv[1]=1;
	for(int i=2;i<=N;i++)
	{
     
		inv[i]=(mod-mod/i)*inv[mod%i]%mod;
		fac[i]=fac[i-1]*i%mod;
		facinv[i]=facinv[i-1]*inv[i]%mod;
	}
	read(n);
	for(int i=1;i<=n;i++)
	{
     
		read(x);
		cnt[x]++;
	}
	for(int i=1;i<N;i++)
	{
     
		for(int j=2;j*i<N;j++)cnt[i]+=cnt[i*j];
	}
	x=1;
	while(!check(x)&&x<=7)x++;
	if(x>7)puts("-1");
	else printf("%d\n",x);
}

T3莫队 由于 D a w n Dawn Dawn太菜了所以放弃了
有问题可以写到下面的评论区或者加 Q Q 407694747 QQ407694747 QQ407694747我们一起讨论
各路神犇各位大佬多多指教

你可能感兴趣的:(集训)