zoukankan      html  css  js  c++  java
  • Codeforces Hello 2019

    Hello 2019

    • 手速场qwq
    • 反正EGH太神仙了啊.jpg
    • 考试的时候不会啊.jpg

    A

    暴力.jpg

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    char opt[10],s[10];
    int main()
    {
    	scanf("%s",s+1);
    	for(int i=1;i<=5;i++)
    	{
    		scanf("%s",opt+1);
    		if(opt[1]==s[1]||opt[2]==s[2])return puts("YES"),0;
    	}
    	puts("NO");
    	return 0;
    }
    

    B

    好像也是傻逼题吧?

    感觉题意好难理解啊...

    然后直接DP.jpg

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    #define N 16
    int a[N],now,ans,n;
    void dfs(int dep,int now)
    {
    	if(dep==n+1){if(!now)ans=1;return ;}
    	dfs(dep+1,(now+a[dep])%360),dfs(dep+1,(now-a[dep]+360)%360);
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);dfs(1,0);
    	puts(ans?"YES":"NO");
    }
    

    C

    维护俩信息就好了

    $a[i][0],a[i][1]$分别表示左侧多了$i$个左括号,右侧多了$i$个右括号的方案数...

    然后就完事了.jpg

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    #define N 500005
    #define ll long long
    char s[N];
    int n,a[N][2],tmp;long long ans;
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%s",s+1);int len=strlen(s+1),now=0,hav=0;
    		for(int j=1;j<=len;j++)
    		{
    			if(s[j]=='(')now++;
    			else
    			{
    				if(!now)hav++;
    				else now--;
    			}
    		}
    		if(hav&&now)continue;
    		if(now)a[now][0]++;
    		else if(hav)a[hav][1]++;
    		else tmp++;
    	}
    	ans=tmp>>1;
    	for(int i=1;i<=500000;i++)ans+=min(a[i][0],a[i][1]);
    	printf("%lld
    ",ans);
    }
    

    D

    是我太菜.jpg

    这个题切不掉真的是傻了啊.jpg

    花了好久才搞出来,期间还有来自$app$的提示.jpg

    我们发现答案具有积性,也就是说,直接对每个质数维护一遍即可.jpg

    $f[i][j]$表示,当前这个质数还有$j$个,已经做了$i$次操作的概率...

    转移的话...就直接每个操作的概率做一下就好了.jpg

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    #define N 60
    #define K 10005
    #define mod 1000000007 
    #define ll long long
    ll P=1,Q;
    ll a[N],b[N];
    int cnt;
    ll qpow(ll x,ll n){ll ret=1;for(;n;n>>=1,x=x*x%mod)if(n&1)ret=ret*x%mod;return ret;}
    struct WC
    {
    	ll x,y;
    	WC operator + (const WC &a) const
    	{
    		WC re;
    		re.x=a.x*y%mod+a.y*x%mod;
    		re.y=a.y*y%mod;
    		return re;
    	}
    	WC operator * (const WC &a) const 
    	{
    		WC re;
    		re.x=a.x*x%mod;
    		re.y=a.y*y%mod;
    		return re;
    	}
    	WC operator * (ll b) const
    	{
    		WC re;
    		(re.x=x*b)%=mod; re.y=y;
    		return re;
    	}
    }f[K][N];
    int main()
    {
    	ll n,k; cin >> n >> k ;
    	for(ll i=2;i*i<=n;i++)
    	{
    		if(n%i==0)
    		{
    			a[++cnt]=i; while(n%i==0) b[cnt]++,n/=i;
    		}
    	}
    	if(n!=1) a[++cnt]=n,b[cnt]=1;
    	WC Ans=(WC){1,1},Now=(WC){0,1};
    	for(int i=1;i<=cnt;i++)
    	{
    		for(int j=0;j<=k;j++)
    		{
    			for(int l=0;l<=b[i];l++)
    			{
    				f[j][l]=(WC){0,1};
    			}
    		}
    		f[0][b[i]]=(WC){1,1};
    		for(int j=1;j<=k;j++)
    		{
    			for(int l=0;l<=b[i];l++)
    			{
    				for(int r=l;r<=b[i];r++)
    				{
    					f[j][l]=f[j][l]+(f[j-1][r]*(WC){1ll,r+1});
    				}
    			}
    		}
    		Now=(WC){0,1};
    		for(int j=0;j<=b[i];j++) Now=Now+(f[k][j]*qpow(a[i],j));
    		Ans=Ans*Now;
    	}
    	cout << Ans.x*qpow(Ans.y,mod-2)%mod << endl ;
    	return 0;
    }
    

    E

    不会

    F

    直接bitset就可以了...

    然后维护俩bitset,分别表示:这个集合所有数的约数的bitset,莫比乌斯函数的是否为$0$的bitset

    然后就可以了...

    原理嘛...直接用容斥原理推就好了.jpg

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    #define N 100005
    bitset<7005>ans[N],G[7005],F[7005];
    int miu[7005],pri[7005],vis[7005],cnt;
    void Miu()
    {
    	miu[1]=1;
    	for(int i=2;i<=7000;i++)
    	{
    		if(!vis[i])pri[++cnt]=i,miu[i]=-1;
    		for(int j=1;j<=cnt&&i*pri[j]<=7000;++j)
    		{
    			vis[i*pri[j]]=1;if(i%pri[j]==0)break;
    			miu[i*pri[j]]=-miu[i];
    		}
    	}
    } 
    int n,Q,op,x,y,z;
    int main() {
    	Miu();
    	for(int i=1;i<=7000;i++)
    		for(int j=i;j<=7000;j+=i)
    			G[j][i]=1,F[i][j]=(miu[j/i]?1:0);
    	scanf("%d%d",&n,&Q);
    	while(Q--)
    	{
    		scanf("%d%d%d",&op,&x,&y);
    		if(op==1)ans[x]=G[y];
    		else if(op==2)scanf("%d",&z),ans[x]=ans[y]^ans[z];
    		else if(op==3)scanf("%d",&z),ans[x]=ans[y]&ans[z];
    		else printf("%d",((ans[x]&F[y]).count()&1));
    	}puts("");
    }
    

    G

    比赛的时候不会第二类斯特林数真是遗憾.jpg

    直接斯特林数反演一下:$x^K=sumlimits_{k=0}{K,k } imes (x,k) imes k!$

    然后就是$ans=sumlimits_{xsubset {1,2,3...n},x eq 0}sumlimits_{k=0}^{kle f(x)}{K,k} imes (f(x),k) imes k!$

    换一个枚举顺序就变成了$ans=sumlimits_{k=0}{K,k} imes k!sumlimits_{xsubset{1,2,3...n}}(f(x),k)$

    然后就可以把问题转化为维护一个$f(x)$的组合数,项数最多为$K$项,也就是变成了一个$O(nk)$的树上背包问题

    转移:$f[x][i]=g[i]+sumlimits_{j=0}^{i-1}g[j] imes f[to][i-j]$,意义:$(f(x),i)=sumlimits_{j=0}^{i-1}(f(x)-i+j,j)$

    然后可以在每个位置更新答案,也就是$ans[i]+=sumlimits_{j=1}^{i-1}g[j] imes f[to][i-j]$,同样,直接其他就不选了的方案贡献出来

    然后同时也需要处理每条边的贡献:$f[to][i]+=f[to][i-1] imes (i eq1?1:1-2^{-siz[to]})$表达的含义很简单,就是这个子树里选择了一个节点的概率,也就是这条边对答案的贡献...

    并且也需要考虑贡献答案,$ans[i]+=f[to][i-1] imes (i==1?1:1-2^{-siz[to]}) imes (1-2^{siz[to1]-n})$,同样,代表的意义是处理这个子树之外,其他的节点至少选了一个的概率...

    因为对于$(f(x),1)=f(x)$,所以直接将所有的边的概率相加即可,也就是上述式子。

    然后就完事了.jpg

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    #include <bitset>
    using namespace std;
    #define N 100005
    #define M 205
    #define ll long long
    #define mod 1000000007
    int q_pow(int x,int n){int ret=1;for(;n;n>>=1,x=(ll)x*x%mod)if(n&1)ret=(ll)ret*x%mod;return ret;}
    #define inv(x) q_pow(x,mod-2)
    struct node{int to,next;}e[N<<1];
    int head[N],siz[N],cnt,f[N][M],s[M][M],fac[M],mi[N],ans[M],n,K;
    inline void add(int x,int y){e[cnt]=(node){y,head[x]};head[x]=cnt++;}
    void dfs(int x,int from)
    {
    	siz[x]=1;f[x][0]=1;
    	for(int i=head[x];i!=-1;i=e[i].next)
    	{
    		int to1=e[i].to;
    		if(to1!=from)
    		{
    			dfs(to1,x);
    			for(int j=min(siz[to1],K)-1;~j;j--)
    			{
    				int val=f[to1][j];
    				if(!j)val=(ll)val*(1-mi[siz[to1]])%mod;
    				ans[j+1]=(ans[j+1]+(ll)val*(1-mi[n-siz[to1]]))%mod;
    				f[to1][j+1]=(f[to1][j+1]+val)%mod;
    			}
    			for(int j=min(siz[x]-1,K);~j;j--)
    				for(int k=1;k<=siz[to1]&&j+k<=K;k++)
    				{
    					int val=(ll)f[to1][k]*f[x][j]%mod;
    					if(j)ans[j+k]=(ans[j+k]+val)%mod;
    					f[x][j+k]=(f[x][j+k]+val)%mod;
    				}
    			siz[x]+=siz[to1];
    		}
    	}
    }
    #define inv2 500000004
    int main()
    {
    	scanf("%d%d",&n,&K);memset(head,-1,sizeof(head));s[0][0]=1;
    	mi[0]=1;for(int i=1;i<=n;i++)mi[i]=(ll)mi[i-1]*inv2%mod;
    	for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);dfs(1,0);
    	for(int i=1;i<=K;i++)for(int j=1;j<=i;j++)s[i][j]=((ll)s[i-1][j]*j+s[i-1][j-1])%mod;
    	fac[0]=1;for(int i=1;i<=K;i++)fac[i]=(ll)fac[i-1]*i%mod;int ret=0;
    	for(int i=1;i<=K;i++)ret=(ret+(ll)s[K][i]*ans[i]%mod*fac[i])%mod;ret=(ll)ret*q_pow(2,n)%mod;
    	printf("%d
    ",(ret+mod)%mod);
    }
    
    //   
    

    H

    感觉能做,口胡一发

    做一个以$d$为底的倍增,维护这样的信息:$f[i][j]$表示,在原数组$d^i+n$这么长,在原数组$+j$之后的$bitset$大小关系情况。

    然后每次倍增求出$f[i+1][j]+=sumlimits_{k=0}^df[i][(j+gen[d])%m]$

    这里的转移没想清楚...但是大概是这个样子,然后对$r$和$l-1$分别做一下就好了.jpg

    没有代码.jpg

  • 相关阅读:
    mysql 约束条件 外键 forigen key 介绍
    【洛谷P4655】Building Bridges
    【CF1139D】Steps to One
    【YbtOJ#20073】钻石守卫
    【YbtOJ#20072】相似子串
    【YbtOJ#20071】礼物购买
    【洛谷P4149】Race
    【洛谷P2059】卡牌游戏
    【CF140C】New Year Snowmen
    【GMOJ4282】平方数游戏
  • 原文地址:https://www.cnblogs.com/Winniechen/p/10353348.html
Copyright © 2011-2022 走看看