zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 94 题解

    终于补完这场了(bushi

    A:

    题意:

    定义相似(similar) 是有一个相同位置的字母相同。

    你要构造一个字符串 (w) 使得和所有 (s) 中长度为 (n) 的子串相似((s) 的长度为 (2 imes n-1))。

    观察法可得是 (s{1,3,5,7,...,2 imes n-1})

    #include<cstdio>
    char s[101];
    int main(){
    	int test;
    	scanf("%d",&test);
    	while(test--){
    		int n;
    		scanf("%d",&n);
    		scanf("%s",s+1);
    		for(int i=1;i<=n;i++)
    			printf("%c",s[i*2-1]);
    		printf("
    ");
    	}
    }
    

    B:

    题意:

    你是一个人,你还有一个随从(

    你的能力值为 (p),你的随从的能力值为 (f)

    两种武器,都有一定的数量和重量。

    最多能拿多少武器。

    brute force

    #include<cstdio>
    int max(int x,int y){return x>y?x:y;}
    int min(int x,int y){return x<y?x:y;}
    int main(){
    	int test;
    	scanf("%d",&test);
    	while(test--){
    		int a,b,c,d,e,f;
    		scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
    		if(e>f){
    			e^=f^=e^=f;
    			c^=d^=c^=d;
    		}
    		int ans=0;
    		for(int i=0;i<=c&&1ll*e*i<=a;i++){
    			int j=min(d,(a-e*i)/f);
    			int rest_c=c-i;
    			int rest_d=d-j;
    			int x=min(rest_c,b/e);
    			int y=min(rest_d,(b-e*x)/f);
    			ans=max(ans,i+j+x+y);
    		}
    		printf("%d
    ",ans);
    	}
    }
    

    C:

    题意:

    给你一个字符串 (s)。要构造一个 (w) 使得通过给定的操作使它变成 (s)
    不能就 "-1"。

    操作方式是 (s_i = w_{i-x}|w_{i+x})

    简单构造,考虑全部变成 0,能填就填,不能填就 -1。

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int test;
    	cin>>test;
    	while(test--){
    		string s;
    		cin>>s;
    		int x;
    		cin>>x;
    		int n=s.length();
    		string answer(n,'0');
    		for(int i=0;i<n;i++){
    			if(s[i]=='0'){
    				if(i-x>=0&&answer[i-x]=='1'){
    					answer="-1";
    					break;
    				}
    			} else {
    				if(i-x>=0&&answer[i-x]=='1'){
    					continue;
    				}
    				if(i-x>=0&&(i<2*x||s[i-2*x]=='1')){
    					answer[i-x]='1';
    				} else if(i+x>=n) {
    					answer="-1";
    					break;
    				} else {
    					answer[i+x]='1';
    				}
    			}
    		}
    		cout<<answer<<'
    ';
    	}
    }
    

    D:

    题意:

    求多少对 (1leq i<j<k<lleq n,a_i=a_k,a_j=a_l)

    首先我们考虑一个前缀和之类的东西。

    枚举 (k),然后更新 (k) 这个位置带来的贡献,并记录一个 (cnt) 数组来存这一对出现了多少次,然后把 (k) 往前移动的时候前缀和统计一下后面的状态,然后再令 (j=k-1),枚举一个 (i),加一下即可。

    但是发现这个前缀和是没有必要的,可以直接做。

    
    #include<bits/stdc++.h>
    using namespace std;
    int a[3001];
    const int MAX=3001*3001;
    int cnt[MAX];
    
    int main(){
    	int test;
    	cin>>test;
    	while(test--){
    		int n;
    		cin>>n;
    		for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cnt[i*n+j]=0;
    		for(int i=1;i<=n;i++)cin>>a[i];
    		long long answer=0;
    		for(int k=n;k;--k){
    			for(int l=k+1;l<=n;l++)
    				cnt[a[k]*n+a[l]]++;
    			int j=k-1;
    			for(int i=1;i<j;i++)
    				answer+=cnt[a[i]*n+a[j]];
    		}
    		cout<<answer<<'
    ';
    	}
    }
    

    E:

    题意同 448C。

    我抄我自己。

    考虑暴力分治递归即可。

    #include<cstdio>
    int n,a[5001];
    
    int min(int x,int y){return x<y?x:y;}
    int solve(int l,int r,int lst){
    	if(l>r)return 0;
    	int mn=1e9;
    	for(int i=l;i<=r;i++)mn=mn<a[i]?mn:a[i];
    	int pre=l,ans=mn-lst;
    	for(int i=l;i<=r;i++)
    		if(a[i]==mn){
    			ans+=solve(pre,i-1,mn);
    			pre=i+1;
    		}
    	ans+=solve(pre,r,mn);
    	return min(ans,r-l+1);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	printf("%d",solve(1,n,0));
    	return 0;
    }
    

    F:

    题意:

    定义 (f(l,r))(l)~(r) 的数位之和。

    我们定义一个子串是 (x-prime) 有三个条件。

    (f(l,r) = x)

    没有 (f(l2,r2)!=x)

    没有 (x mid f(l2,r2))

    ([lleq l2,r2leq r])

    删除最小的字符个数使得给出的字符串 (s) 不包含 (x-prime) 的子串。

    简单题。

    (xleq 20) ,就考虑 (brute) 出来 (x-prime) 的所有合法情况。

    然后一个个插到字典树上,AC自动机跑一遍,求出 (fail) 之后简单 (dp) 即可。

    #include<bits/stdc++.h>
    
    const int MAXNODE=10005;
    struct acam{
    	int tr[MAXNODE][10];
    	int fail[MAXNODE];
    	bool ed[MAXNODE];
    	int _=1;
    	
    	int newnode(){
    		return ++_;
    	}
    	
    	void insert(std::vector<int>a){
    		int p=1;
    		for(auto i:a){
    			int&nxt=tr[p][i];
    			if(!nxt)nxt=newnode();
    			p=nxt;
    		}
    		ed[p]=true;
    	}
    	
    	void build(){
    		std::queue<int>q;
    		for(int i=1;i<10;i++)
    			if(tr[1][i])
    				fail[tr[1][i]]=1,q.push(tr[1][i]);
    			else
    				tr[1][i]=1;
    		while(!q.empty()){
    			int u=q.front();
    			q.pop();
    			for(int i=1;i<10;i++){
    				if(tr[u][i]){
    					fail[tr[u][i]]=tr[fail[u]][i];
    					ed[i]|=ed[fail[i]];
    					q.push(tr[u][i]);
    				}else tr[u][i]=tr[fail[u]][i];
    			}
    		}
    	}
    }acam;
    
    const int N=1002;
    char s[N];
    int a[N],x;
    
    void dfs(int s,std::vector<int>t){
    	if(s==x){
    		int tmp=0;
    		int sz=t.size();
    		for(int i=0;i<sz;i++){
    			tmp=0;
    			for(int j=i;j<sz;j++){
    				tmp+=t[j];
    				if(tmp!=x&&x%tmp==0)return;
    			}
    		}
    		acam.insert(t);
    		return;
    	}
    	for(int i=1;i<10&&s+i<=x;i++){
    		t.push_back(i);
    		dfs(s+i,t);
    		t.pop_back();
    	}
    }
    
    int dp[N][MAXNODE];
    
    int main(){
    	scanf("%s",s+1);
    	int n=strlen(s+1);
    	for(int i=1;i<=n;i++)a[i]=s[i]^'0';
    	scanf("%d",&x);
    	dfs(0,{});
    	acam.build();
    	int allnode=acam._;
    	
    	memset(dp,63,sizeof(dp));
    	dp[1][1]=0;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=allnode;j++){
    			int nxt=acam.tr[j][a[i]];
    			if(!acam.ed[nxt])
    				dp[i+1][nxt]=std::min(dp[i+1][nxt],dp[i][j]);
    			dp[i+1][j]=std::min(dp[i+1][j],dp[i][j]+1);
    		}
    	}
    	
    	int answer=1e9;
    	for(int i=1;i<=allnode;i++)
    		answer=std::min(answer,dp[n+1][i]);
    	
    	printf("%d
    ",answer);
    }
    

    G:

    题意:

    (n) 个人,这 (n) 个人要求选出来的人数的 range 在 ([l_i,r_i])。然后有 (m) 对人相互憎恨。(意思是不能同时选)求选出来的方案数个数。对 998244353 取模。

    我们考虑差分一下。

    rep(i,1,n){int l,r;scanf("%d%d",&l,&r);cnt[L[i]=l]++;cnt[(R[i]=r)+1]--;}rep(i,1,n)add(cnt[i],cnt[i-1]);
    

    这样 (cnt_i) 就是选 (i) 个人的情况下能选的人数了。

    然后考虑组合数一下,显然这个方案数是 (inom{i}{cnt_i})

    我们钦定 (j) 个位置,这个方案数就是 (inom{i-j}{cnt_i-j})

    考虑 (m=0) 的时候这个答案显然是 (sum_{i=1}^{n}inom{i}{cnt_i})

    (m>0) 的时候呢?

    发现有一堆位置是要自己钦定的。

    我们定义 (f_{j,k} = sum_{i=1}^{k}inom{i-j}{cnt_i-j})

    定义一个状态 (state) 是选多对关系情况下的方案数,但是这个玩意会算重复。

    考虑容斥。

    (sum_{t}(-1)^{|t|} inom{|t|}{m}f(t))

    实际上我们是钦定了有关系的那些人 (要去重) 全部都选的时候的方案数减掉。

    #include<cstdio>
    #include<set>
    #define rep(i,x,y) for(int i=x;i<=y;i++)
    int min(int x,int y){return x<y?x:y;}
    int max(int x,int y){return x>y?x:y;}
    const int N=3e5+2;
    int L[N],R[N],fac[N],ifac[N];
    const int mod=998244353;
    int mul(const int&x,const int&y){return 1ll*x*y%mod;}
    void add(int&x,const int&y){x+=y;if(x>=mod)x-=mod;}
    void dec(int&x,const int&y){x-=y;if(x<0)x+=mod;}
    int qpow(int base,int t){//base^t
    	int result=1;while(t){if(t&1)result=mul(result,base);base=mul(base,base);t>>=1;}return result;
    }
    int C(int x,int y){if(x<y||x<0||y<0)return 0;return mul(fac[x],mul(ifac[x-y],ifac[y]));}
    int n,m,cnt[N],f[41][N];
    int A[20],B[20];
    int main(){
    	fac[0]=ifac[0]=1;rep(i,1,N-1)fac[i]=mul(fac[i-1],i),ifac[i]=qpow(fac[i],mod-2);
    	scanf("%d%d",&n,&m);
    	rep(i,1,n){int l,r;scanf("%d%d",&l,&r);cnt[L[i]=l]++;cnt[(R[i]=r)+1]--;}rep(i,1,n)add(cnt[i],cnt[i-1]);
    //	rep(i,1,n)printf("cnt[%d]=%d
    ",i,cnt[i]);
    	rep(j,0,2*m)rep(i,1,n)f[j][i]=f[j][i-1],add(f[j][i],C(cnt[i]-j,i-j));
    	rep(i,0,m-1)scanf("%d%d",&A[i],&B[i]);
    	int up=1<<m,answer=0;
    	rep(i,0,up-1){
    		int l=1,r=n;
    		std::set<int>s;
    		rep(j,0,m-1)if(i>>j&1)l=max(l,max(L[A[j]],L[B[j]])),r=min(r,min(R[A[j]],R[B[j]])),s.insert(A[j]),s.insert(B[j]);
    		if(l>r)continue;
    		int sz=(int)s.size();
    		int tmp=(f[sz][r]-f[sz][l-1]+mod)%mod;
    		if(__builtin_popcount(i)&1)dec(answer,tmp);else add(answer,tmp);
    	}
    	printf("%d
    ",answer);
    	return 0;	
    }
    
  • 相关阅读:
    kuangbin_ShortPath P (HDU 4725)
    kuangbin_ShortPath O (LightOJ 1074)
    方法的定义格式
    A Better Finder Rename 9.40 Key
    [iOS] 初探 iOS8 中的 Size Class
    iOS 后台执行
    iOS7 毛玻璃效果
    PhpStorm8 注册码
    [教程] 【终极开关机加速!!】手把手教你加速Mac的开关机速度。(经验证适用10.10!)
    iOS 取应用版本
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/13565342.html
Copyright © 2011-2022 走看看