zoukankan      html  css  js  c++  java
  • [NOIP模拟25]题解

    A.字符串

    Catalan数不能再裸了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll mod=20100403;
    const int N=2000005;
    ll n,m;
    ll fac[N];
    ll qpow(ll a,ll b)
    {
        ll res=1;a=a%mod;
        while(b)
        {
            if(b&1)res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    ll C(ll x,ll y)
    {
        if(y>x)return 0;
        return fac[x]*(qpow(fac[y]*fac[x-y]%mod,mod-2))%mod;
    }
    ll lucas(ll x,ll y)
    {
        if(!y)return 1;
        return C(x%mod,y%mod)*lucas(x/mod,y/mod)%mod;
    }
    void ini()
    {
        fac[0]=1;
        for(ll i=1;i<=m+n;i++)
            fac[i]=fac[i-1]*1LL*i%mod;
        
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        ini();
        ll ans=(lucas(m+n,m)-lucas(m+n,m-1)+mod)%mod;
        cout<<ans<<endl;
        return 0;
    }
    View Code

    B.乌鸦喝水

    很能开阔思路的乱搞题。对于每一个缸算出它最多下降的次数,连同它所在的位置进行二元组排序。设rest表示剩下多少缸还能喝,now表示过了几轮,total表示一共喝了多少次水,num[]表示每个缸喝的次数。显然所求即为$sum num[i]$

    对于每一个缸,二分它还能被喝几轮,如果第i个缸还能喝cnt轮,后面(排序后)的缸自然也可以喝cnt轮。易得$num[i]=now+cnt$,之后用树状数组判断位置在i之前的缸能否让它再喝一次,即剩下的次数是否大于等于在该缸之前(包括)的缸数,如果是的话now和num[]都要++。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    typedef long long ll;
    #define pa pair<ll,ll>
    const int N=100005;
    int n,m,tot,rest,now;
    ll x,w[N],a[N],num[N],cnt,total,ans;
    pa bu[N];
    namespace bit
    {
        ll c[N];
        int lb(int x){return x&-x;}
        void add(int x)
        {
            for( ;x<=n;x+=lb(x))
                c[x]++;
        }
        int ask(int x)
        {
            int res=0;
            for( ;x;x-=lb(x))
                res+=c[x];
            return res;
        }
    }
    int main()
    {
        scanf("%d%d%lld",&n,&m,&x);
        for(int i=1;i<=n;i++)
            scanf("%lld",&w[i]);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)
            if(x>=w[i])bu[++tot]=make_pair((x-w[i])/a[i]+1,tot);
        sort(bu+1,bu+tot+1);
        rest=tot;
        for(int i=1;i<=tot;i++)
        {
            int l=0,r=m-now;
            while(l<=r)
            {
                int mid=l+r>>1;
                if(1LL*rest*mid<bu[i].first-total)l=mid+1,cnt=mid;
                else r=mid-1;
            }
            if(now+cnt==m)
            {
                ans+=(tot-i+1)*m;
                cout<<ans<<endl;
                exit(0);
            }
            num[i]=now+cnt;
            int pre=bu[i].second-bit::ask(bu[i].second);
            bit::add(bu[i].second);
            if(bu[i].first-rest*cnt-total>=pre)total++,num[i]++;
            total+=cnt*rest,now+=cnt;
            rest--;
            ans+=num[i];
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    C.所驼门王的宝藏

    十分不敢相信居然会有这么水的省选题……

    可以发现跳过去再跳过来的情况对统计答案造成了困难,所以考虑缩点。把整张图缩成一个森林之后我们要让它经过的点尽量多,所以找联通的最长链。

    一句话题解:将每个格子和它能到达的格子暴力连边,然后Tarjan缩点,最后跑一遍拓扑求树上最长链就是答案。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int M=1000005,N=1e5+5;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    struct room_
    {
        int x,y,op;
    }a[N];
    int n,R,C;
    vector<int> h[M],l[M],g[N];
    int tot,head[M<<2],nxt[M<<2],to[M<<2],deg[N],ans[N];
    void add(int x,int y)
    {
        to[++tot]=y;
        nxt[tot]=head[x];
        head[x]=tot;
    }
    int dfn[N],low[N],st[N],top=0,vis[N],bel[N],scc,ind,size[N];
    void tarjan(int x)
    {
        dfn[x]=low[x]=++ind;
        vis[x]=1;
        st[++top]=x;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(!dfn[y])tarjan(y),low[x]=min(low[x],low[y]);
            else if(vis[y])low[x]=min(low[x],dfn[y]);
        }
        if(low[x]==dfn[x])
        {
            scc++;int now=0;
            do
            {
                now=st[top--];
                size[scc]++;
                bel[now]=scc;
                vis[now]=0;
            }while(now!=x);
        }
    }
    int main()
    {
        n=read();R=read();C=read();
        for(int i=1;i<=n;i++)
        {
            a[i].x=read(),a[i].y=read(),a[i].op=read();
            h[a[i].x].push_back(i);l[a[i].y].push_back(i);
        }
        for(int i=1;i<=n;i++)
        {
            int op=a[i].op;
            if(op==1)
            {
                int sz=h[a[i].x].size();
                for(int j=0;j<sz;j++)
                {
                    if(h[a[i].x][j]==i)continue;
                    add(i,h[a[i].x][j]);
                }
            }
            else if(op==2)
            {
                int sz=l[a[i].y].size();
                for(int j=0;j<sz;j++)
                {
                    if(l[a[i].y][j]==i)continue;
                    add(i,l[a[i].y][j]);
                }
            }
            else if(op==3)
            {
                int sz;
                if(a[i].x>1)
                {
                    sz=h[a[i].x-1].size();
                    for(int j=0;j<sz;j++)
                    {
                        if(a[h[a[i].x-1][j]].y>=a[i].y-1&&a[h[a[i].x-1][j]].y<=a[i].y+1)
                            add(i,h[a[i].x-1][j]);
                    }
                }
                sz=h[a[i].x].size();
                for(int j=0;j<sz;j++)
                {
                    if(h[a[i].x][j]==i)continue;
                    if(a[h[a[i].x][j]].y>=a[i].y-1&&a[h[a[i].x][j]].y<=a[i].y+1)
                        add(i,h[a[i].x][j]);
                }
                if(a[i].x<R)
                {
                    sz=h[a[i].x+1].size();
                    for(int j=0;j<sz;j++)
                    {
                        int now=h[a[i].x+1][j];
                        if(a[now].y>=a[i].y-1&&a[now].y<=a[i].y+1)
                            add(i,now);
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])tarjan(i);
        for(int x=1;x<=n;x++)
            for(int i=head[x];i;i=nxt[i])
            {
                int y=to[i];
                if(bel[y]!=bel[x])
                    g[bel[x]].push_back(bel[y]),deg[bel[y]]++;
            }
        
        //debug();
        //puts("----------------------------------------");
    /*    for(int i=1;i<=scc;i++)
            if(!v[i])
            {
                num=0,dfs(i);
            }*/
        queue<int> q;
        for(int i=1;i<=scc;i++)
            if(!deg[i])q.push(i),ans[i]=size[i];
        while(!q.empty())
        {
            int x=q.front();
            q.pop();int sz=g[x].size();
            for(int i=0;i<sz;i++)
            {
                int y=g[x][i];
                ans[y]=max(ans[y],ans[x]+size[y]);
                if(!(--deg[y]))q.push(y);
            }
        }
        cout<<*max_element(ans+1,ans+1+scc)<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    mysql语句
    jsp中调用javabean
    java内存分配
    BaseClasses学习(-)CAMEvent
    YUV格式入门
    gcc intrinsic vector
    GCC builtin vector (gcc内建函数)学习
    GNU 内联汇编学习(1)
    express 中间件
    《饿了么大前端 Node.js 进阶教程》—Javascript 基础问题—引用传递
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/11373906.html
Copyright © 2011-2022 走看看