ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Educational Codeforces Round 81

2022-01-21 16:35:28  阅读:195  来源: 互联网

标签:Educational 81 int Codeforces long while typedef include define


Link

VP 了这场,做出了 ABCDE。

B 题罚时四次是因为没想清楚就开冲,十分不冷静,甚至有一次忘记删调试就交了(但它能过第一个样例所以算罚时(哭))。

E 题想了个巨复杂的做法,差点没写完,但实际上有简单很多的做法,VP 的时候好像有一个瞬间这个做法一闪而过,不知道为啥没去往下想。

A

最终答案一定形如 7111.. 或者 111...,对 \(n\) 的奇偶性讨论一下即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
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<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
void sol()
{
    int n=read();
    if(n==2)puts("1");
    else if(n==3)puts("7");
    else{
        if(n%2)putchar('7');
        else putchar('1');
        for(int i=1;i<n/2;i++)putchar(49);
        puts("");
    }
}
int main()
{
    int T=read();
    while(T--)sol();
}

B

令 \(0\) 的权值为 \(+1\),\(1\) 的权值为 \(-1\),那么就是问这个长度为无穷大的字符串有多少个权值前缀和为 \(x\)。开个桶记一下 \(s\) 前缀和的值的出现次数,那么一个值 \(v\) 能有贡献当且仅当 \(x\equiv v\pmod sum\),\(sum\) 表示 \(s\) 的权值总和。需要特判 \(sum=0\) 的情况。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
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<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
const int N=2e5+10;
char s[N];
int cnt[N<<1];
void sol()
{
    int n=read(),x=read();
    scanf("%s",s+1);
    for(int i=0;i<=n*2;i++)cnt[i]=0;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='1')sum--;
        else sum++;
        cnt[sum+n]++;
    }
    if(sum==0)
    {
        if(x+n>=0&&x+n<=2*n&&cnt[x+n])puts("-1");
        else puts("0");
    }
    else
    {
        int ans=0;
        if(!x)ans++;
        for(int i=-n;i<=n;i++)
        {
            if(x<=i&&sum<0&&(i%(-sum)-sum)%(-sum)==(x%(-sum)-sum)%(-sum))ans+=cnt[n+i];
            if(x>=i&&sum>0&&(i%sum+sum)%sum==(x%sum+sum)%sum)ans+=cnt[n+i];
        }
        printf("%d\n",ans);
    }
}
int main()
{
    int T=read();
    while(T--)sol();
}

C

对 \(s\) 建出子序列自动机,\(t\) 在子序列自动机上匹配,计算匹配轮数。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
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<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
const int N=1e5+10;
int nxt[N][26],pos[26];
char s[N],t[N];
void sol()
{
    scanf("%s%s",s+1,t+1);
    int n=strlen(s+1),m=strlen(t+1);
    memset(pos,0,sizeof(pos));
    for(int i=n;i;i--)
    {
        for(int j=0;j<26;j++)
            nxt[i][j]=pos[j];
        pos[s[i]-'a']=i;
    }
    for(int j=0;j<26;j++)nxt[0][j]=pos[j];
    int ans=0;
    for(int i=1;i<=m;)
    {
        ans++;
        int pre=i;
        int j=0;
        while(1)
        {
            // printf("i=%d\n",i);
            if(nxt[j][t[i]-'a'])j=nxt[j][t[i]-'a'],i++;
            else {break;}
            if(i>m)break;
            // printf("j=%d\n",j);
        }
        if(pre==i)return puts("-1"),void();
    }
    printf("%d\n",ans);
}
int main()
{
    int T=read();
    while(T--)sol();
    return 0;
}

D

设 \(g=\gcd(a,m)\),那么 \(\gcd(\frac{a}{g}+\frac{x}{g},\frac{m}{g})=1\),那这大概就是一个和 \(\varphi\) 有关的东西,结合样例大胆猜想答案是 \(\varphi(\frac{m}{g})\),然后就过了。

证明并不困难,考虑到 \(0\le \frac xg<\frac mg\),那 \(\frac ag+\frac xg\) 一定会覆盖到模 \(\frac mg\) 意义下的所有值且每个值只覆盖一次。而根据辗转相除法 \(\gcd(\frac ag+\frac xg,\frac mg)=\gcd((\frac ag + \frac mg)\bmod \frac mg,\frac mg)\),也就是说上面要求的东西等价于 \(\sum_{i=0}^{\frac mg-1}[\gcd(i,\frac mg)=1]\),即 \(\varphi(\frac mg)\)。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<ctime>
using namespace std;
#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
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<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
int phi(int n) 
{
    int ans=n;
    for(int i=2;i*i<=n;i++) 
    {
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0) n/=i;
        }
    }
    if(n>1)ans=ans/n*(n-1);
    return ans;
}
void sol()
{
    int a=read(),m=read();
    int g=gcd(a,m);
    printf("%lld\n",phi(m/g));
}
signed main()
{
    int T=read();
    while(T--)sol();
}

E

枚举最终左边集合的最大值 \(x\),考虑分界点 \(l\) 在哪里时 \(p_i\) 会产生代价。设 \(pos_i\) 表示数值 \(i\) 在排列中的位置,不难发现当 \(pos_i>l\) 且 \(i\le x\) 时或者 \(pos_i\le l\) 且 \(i>x\) 时会产生 \(a_i\) 的代价,线段树维护这个东西(详见代码),\(x\) 增加时单点修改,每次都取个全局 \(\min\)。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<ctime>
using namespace std;
#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
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<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
int phi(int n) 
{
    int ans=n;
    for(int i=2;i*i<=n;i++) 
    {
        if(n%i==0)
	{
            ans=ans/i*(i-1);
            while(n%i==0) n/=i;
        }
    }
    if(n>1) ans=ans/n*(n-1);
    return ans;
}
void sol()
{
    int a=read(),m=read();
    int g=gcd(a,m);
    printf("%lld\n",phi(m/g));
}
signed main()
{
    int T=read();
    while(T--)sol();
}

F

基本上是从这里抄的

首先把期望转化为合法方案数除以总方案数。

把给定区间弄成左闭右开的,然后把端点离散化,设端点从小到大为 \(t_1,t_2,\cdots,t_m\),那么就有了 \(m-1\) 个区间 \([t_1,t_2),[t_2,t_3),\cdots,[t_{m-1},t_m)\)。设 \(f_{i,j}\) 表示考虑前 \(i\) 个数,第 \(i\) 个数放在第 \(j\) 个区间的方案数,枚举前面的区间放的数量 \(k\),有转移:

\[f_{i,j}=\sum_{k<i}\binom{t_{j+1}-t_j+i-k-1}{t_{j+1}-t_j-1}\sum_{s>j}f_{k,s} \]

其实就是个插板法。

答案就是:

\[\frac{\sum_{i=1}^{m-1} f_{n,i}}{\prod_{i=1}^n (r_i-l_i+1)} \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
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<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
void write(int n)
{
	if(n<0){putchar('-');n=-n;}
	if(n>9)write(n/10);
	putchar(n%10^48);
}
const int N=110,mod=998244353;
int qpow(int a,int n)
{
	int ans=1;
	while(n){
		if(n&1)ans=1ll*a*ans%mod;
		a=1ll*a*a%mod;
		n>>=1;
	}
	return ans;
}
int binom(int n,int m)
{
	if(n<m)return 0;
	int ans=1;
	for(int i=1;i<=m;i++)ans=1ll*ans*qpow(i,mod-2)%mod*(n-i+1)%mod;
	return ans;
}
int f[N][N];
int l[N],r[N],t[N];
int main()
{
	int n=read(),m=0;
//	for(int i=1;i<=n;i++)
//	{
//		for(int j=0;j<=i;j++)printf("%d ",binom(i,j));
//		puts("");
//	}
	for(int i=1;i<=n;i++)t[++m]=l[i]=read(),t[++m]=r[i]=read()+1;
//	for(int i=1;i<=n;i++)printf("[%d, %d)\n",l[i],r[i]);
	sort(t+1,t+m+1),m=unique(t+1,t+m+1)-t-1;
	for(int i=1;i<=n;i++)l[i]=lower_bound(t+1,t+m+1,l[i])-t,r[i]=lower_bound(t+1,t+m+1,r[i])-t;
//	for(int i=1;i<=m;i++)printf("t[%d]=%d\n",i,t[i]);
	f[0][m]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<m;j++)
		{
			for(int k=i-1;k>=0;k--)
			{
				if(l[k+1]>j||j>r[k+1]-1)break;
				int sum=0;
				for(int t=j+1;t<=m;t++)sum+=f[k][t],sum%=mod;
				f[i][j]+=binom(t[j+1]-t[j]+i-k-1,i-k)*1ll*sum%mod;
				f[i][j]%=mod;
			}
		}
	}
	int ans=0;
	for(int i=1;i<m;i++)ans+=f[n][i],ans%=mod;
	for(int i=1;i<=n;i++)ans=1ll*ans*qpow(t[r[i]]-t[l[i]],mod-2)%mod;
	printf("%d",ans);
	return 0;
}

标签:Educational,81,int,Codeforces,long,while,typedef,include,define
来源: https://www.cnblogs.com/juruo-zzt/p/15830708.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有