M-SOLUTIONS Programming Contest

AB

签到(A就是ans=180(n-2)所以不放code了)

#include<bits/stdc++.h>
using namespace std;
int n,ans;
char s[100001];
int main()
{
    scanf("%s",s+1);
    n=strlen(s+1),ans=15-n;
    for(int i=1;i<=n;i++)if(s[i]=='o')ans++;
    if(ans>=8)puts("YES");else puts("NO");
}
View Code

C

考虑枚举输的人赢了几次,然后知道不平i局的期望局数即可(这个随便算算就行了)

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7,mod=1e9+7;
int n,a,b,c,ans,fac[N],inv[N],pa[N],pb[N],s[N];
int qpow(int a,int b)
{
    int ret=1;
    while(b)
    {
        if(b&1)ret=1ll*ret*a%mod;
        a=1ll*a*a%mod,b>>=1;
    }
    return ret;
}
int C(int a,int b){return 1ll*fac[a]%mod*inv[a-b]%mod*inv[b]%mod;}
int main()
{
    cin>>n>>a>>b>>c;
    a=1ll*a*qpow(100-c,mod-2)%mod;
    b=1ll*b*qpow(100-c,mod-2)%mod;
    c=1ll*c*qpow(100,mod-2)%mod;
    fac[0]=1;for(int i=1;i<=2*n;i++)fac[i]=1ll*fac[i-1]*i%mod;
    inv[2*n]=qpow(fac[2*n],mod-2);
    for(int i=2*n;i;i--)inv[i-1]=1ll*inv[i]*i%mod;
    pa[0]=pb[0]=1;for(int i=1;i<=2*n;i++)pa[i]=1ll*pa[i-1]*a%mod,pb[i]=1ll*pb[i-1]*b%mod;
    for(int i=1;i<=2*n;i++)s[i]=1ll*i*qpow(mod+1-c,mod-2)%mod;
    for(int i=0;i<n;i++)ans=(ans+(1ll*pa[i]*pb[n]+1ll*pa[n]*pb[i])%mod*s[i+n]%mod*C(i+n-1,i))%mod;
    cout<<ans<<endl;
}
View Code

D

贪心,因为最小值一定会被统计,所以每次可以把最小值选择一个叶节点(仅统计一次),然后删去该叶节点,如此就可以发现其实最优方案是除了最大值每个值都被计入答案一次,构造方法是把c数组从大到小排列,按照dfs序分配(保证儿子的值<父亲)

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+7;
int n,ans,cnt,c[N],s[N];
vector<int>G[N];
void dfs(int u,int fa)
{
    s[u]=c[++cnt];
    for(int i=0;i<G[u].size();i++)if(G[u][i]!=fa)dfs(G[u][i],u);
}
int main()
{
    scanf("%d",&n);
    for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    sort(c+1,c+n+1),reverse(c+1,c+n+1);
    for(int i=2;i<=n;i++)ans+=c[i];
    printf("%d
",ans);
    dfs(1,0);
    for(int i=1;i<=n;i++)printf("%d ",s[i]);
}
View Code

E

Oh,cheese!什么弱智题!然而我想复杂了想到求导和积分去了!做法实际上就是把每一项除以一个d,然后就是阶乘连乘了。

#include<bits/stdc++.h>
using namespace std;
const int mod=1e6+3;
int x,d,n,fac[mod];
int qpow(int a,int b)
{
    int ret=1;
    while(b)
    {
        if(b&1)ret=1ll*ret*a%mod;
        a=1ll*a*a%mod,b>>=1;
    }
    return ret;
}
int main()
{
    fac[0]=1;for(int i=1;i<mod;i++)fac[i]=1ll*fac[i-1]*i%mod;
    int Q;scanf("%d",&Q);
    while(Q--)
    {
        scanf("%d%d%d",&x,&d,&n);
        if(!d)printf("%d
",qpow(x,n));
        else{
            x=1ll*x*qpow(d,mod-2)%mod;
            if(!x||x+n-1>=mod)puts("0");
            else printf("%d
",1ll*fac[x+n-1]*qpow(fac[x-1],mod-2)%mod*qpow(d,n)%mod);
        }
    }
}
View Code

F

什么鬼正解是O(n3/w)?暴力bitset艹过去?然后记录三个数组L[i],R[i],a[i]表示左边打能否胜利、右边打能否胜利、自己能战胜谁,然后直接位运算算一遍就行了。

#include<bits/stdc++.h>
using namespace std;
const int N=2019;
int n,ans;
bitset<N>L[N],R[N],a[N];
char str[N];
int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        scanf("%s",str+1);
        for(int j=1;j<i;j++)a[i][j]=str[j]-'0',a[j][i]='1'-str[j];
    }
    for(int i=1;i<=n;i++)L[i][i]=R[i][i]=1;
    for(int l=2;l<=n;l++)
    for(int i=1,j;i+l-1<=n;i++)
    {
        j=i+l-1;
        L[j][i]=(R[i+1]&L[j]&a[i]).count()!=0;
        R[i][j]=(L[j-1]&R[i]&a[j]).count()!=0;
    }
    for(int i=1;i<=n;i++)ans+=R[1][i]&&L[n][i];
    printf("%d",ans);
}
View Code

result:rank200,rating+=30

原文地址:https://www.cnblogs.com/hfctf0210/p/10961924.html