• 2018.11.3 PION模拟赛


    期望:100    实际:100

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,s,num;
    int a[MAXN];
    long long ans;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int cmp(int x,int y){
        return x>y;
    }
    int main(){
        freopen("median.in","r",stdin);
        freopen("median.out","w",stdout);
        n=read();s=read();
        for(int i=1;i<=n;i++)    a[i]=read();
        sort(a+1,a+1+n,cmp);
        int mid=n/2;
        for(int i=1;i<=n;i++)
            if(a[i]>=s)    num++;
            else{
                if(num<=mid){
                    ans+=(s-a[i]);num++;
                }    
                else if(num>mid)    break;
            }
        cout<<ans;
    }
    100

     期望:20~40    实际:0

    /*
    思路:感觉可以用卡特兰数搞一下。
    应该可以推出递推式。 
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,p,k;
    long long ans;
    int vis[10010];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void dfs(int now,int num1,int num2){
        if(num1>n)    return ;
        if(num1+(2*n-now)+1<n)    return ;
        if(num2-num1>=k)    return ;
        if(now==2*n+1){
            if(num1==n){
                ans+=1;
                ans%=p;
            }
            return ;
        }
        vis[now]=1;dfs(now+1,num1+1,num2);vis[now]=0;
        dfs(now+1,num1,num2+1);
    }
    int main(){
        freopen("term.in","r",stdin);
        freopen("term.out","w",stdout);
        n=read();k=read();p=read();
        if(n<=15){
            dfs(1,0,0);
            printf("%d
    ",ans);
        }
        else if(k==1){
            ans=1;
            for(int i=2*n;i>=n+2;i--){
                int j=2,num=i;
                while(j<=n){
                    if(!vis[j]){
                        if(num%j==0){
                            num/=j;
                            vis[j]=1;
                        }
                    }
                    j++;
                }
                ans=ans*num;
            }
            for(int i=2;i<=n;i++)
                if(!vis[i])    ans/=i;
            cout<<ans%p;
        }
    }
    0

    看出是卡特兰数了,但是对于非质数的除法取莫出现了问题

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,k,p,tot;
    int prime[10000],num[100000];
    int vis[10010],mn[100010],yes[100010];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void pre(){
        memset(yes,true,sizeof(yes));
        yes[1]=false;
        for(int i=2;i<=2*n;i++){
            if(yes[i])    prime[++tot]=i,mn[i]=tot;
            for(int j=1;i*prime[j]<=n;j++){
                yes[i*prime[j]]=false;
                if(i%prime[j]==0)    break;    
            }
        }
    }
    void insert(int x,int opt){
        while(x!=1){
            num[mn[x]]+=opt;
            x=x/prime[mn[x]];
        }
    }
    int fastpow(long long a,long long b){
        long long s=1;
        for(;b;b>>=1){
            if(b&1)    s=a*a%p;
            a=a*a%p;
        }
        return s;
    }
    int findans(){
        long long ans=1;
        for(int i=1;i<=tot;i++)
            if(num[i])
                ans=(1ll*ans*fastpow(prime[i],num[i]))%p;
        return ans;
    }
    int main(){
    //    freopen("term.in","r",stdin);
        //freopen("term.out","w",stdout);
        n=read();k=read();p=read();
        pre();
        for(int i=n+1;i<=2*n;i++)    insert(i,1);
        for(int i=1;i<=n;i++)    insert(i,-1);
        long long ans1=findans();
        memset(num,0,sizeof(num));
        for(int i=n+k+1;i<=2*n;i++)    insert(i,1);
        for(int i=1;i<=n-k;i++)    insert(i,-1);
        long long  ans2=findans();
        cout<<(ans1-ans2+p)%p;
    }
    100

    发现正反跑spfa有70分。

    #include<map>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 500010
    using namespace std;
    map<int,bool>ma[MAXN];
    int tim,top,sumcol;
    int n,m,s,t,tot,tot1,tot2;
    struct nond{ int id,dis; };
    int low[MAXN],dfn[MAXN],col[MAXN];
    int val[MAXN],val1[MAXN],di[MAXN],dis[MAXN];
    int stack[MAXN],vis[MAXN],visstack[MAXN];
    int to[MAXN],cap[MAXN],net[MAXN],head[MAXN];
    int to1[MAXN],cap1[MAXN],net1[MAXN],head1[MAXN];
    int to2[MAXN],cap2[MAXN],net2[MAXN],head2[MAXN];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void add(int u,int v,int w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
    }
    void add2(int u,int v,int w){
        to1[++tot1]=v;cap1[tot1]=w;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void add3(int u,int v,int w){
        to2[++tot2]=v;cap2[tot2]=w;net2[tot2]=head2[u];head2[u]=tot2;
    }
    void tarjin(int now){
        low[now]=dfn[now]=++tim;
        stack[++top]=now;
        vis[now]=1;visstack[now]=1;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(dfn[now]==low[now]){
            sumcol++;
            col[now]=sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;
            }
            visstack[now]=0;
            top--;
        }
    }
    
    void spfa(int S){
        queue<int>que;
        memset(vis,0,sizeof(vis));
        memset(di,0x7f,sizeof(di));
        vis[S]=1;di[S]=val1[S];
        que.push(S);
        while(!que.empty()){
            int now=que.front();
            que.pop();
            vis[now]=0;
            for(int i=head1[now];i;i=net1[i])
                if(di[to1[i]]>=(di[now]&cap1[i]&val1[to1[i]])){
                    di[to1[i]]=(di[now]&cap1[i]&val1[to1[i]]);
                    if(!vis[to1[i]]){
                        vis[to1[i]]=1;
                        que.push(to1[i]);
                    }
                }
        }
    }
    void spfa1(int S){
        queue<int>que;
        memset(vis,0,sizeof(vis));
        memset(dis,0x7f,sizeof(di));
        vis[S]=1;dis[S]=val1[S];
        que.push(S);
        while(!que.empty()){
            int now=que.front();
            que.pop();
            vis[now]=0;
            for(int i=head2[now];i;i=net2[i])
                if(dis[to2[i]]>=(dis[now]&cap2[i]&val1[to2[i]])){
                    dis[to2[i]]=(dis[now]&cap2[i]&val1[to2[i]]);
                    if(!vis[to2[i]]){
                        vis[to2[i]]=1;
                        que.push(to2[i]);
                    }
                }
        }
    }
    int main(){
        freopen("rabbit.in","r",stdin);
        freopen("rabbit.out","w",stdout);
        n=read();m=read();s=read();t=read();
        for(int i=1;i<=n;i++)    val[i]=read();
        for(int i=1;i<=m;i++){
            int u=read();
            int v=read();
            int w=read();
            add(u,v,w);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])    tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        add2(col[i],col[to[j]],cap[j]);
                        add3(col[to[j]],col[i],cap[j]);
                    }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            if(!vis[col[i]])    val1[col[i]]=val[i],vis[col[i]]=1;
            else val1[col[i]]=(val1[col[i]]&val[i]);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]==col[to[j]])
                    val1[col[i]]=(val1[col[i]]&cap[j]);
        spfa(col[s]);
        spfa1(col[t]);
        if(di[col[t]]==0x7f7f7f7f){ puts("-1");return 0; }
        else{ printf("%d
    ",min(di[col[t]],dis[col[s]]));return 0; }
    }
    70tarjin缩点+正反跑spfa
    /*
    ————该题目主要考察tarjan缩点,拓扑排序和贪心
    40pts:
    直接爆搜,看每条边走不走,复杂度 ,此部分分贪心将所有权值&起来是有分的(给对题目做了一定分析的盆友的彩蛋)
    60pts:
    对于M = N - 1的点,其实他并不是树QWQ,因为题目中明确说了不保证联通,所以这个部分分是个假的。但是为了多给大家送点分,此部分数据采用随机生成,不论是用不正确的spfa还是dijkstra都能够跑过去,是不是很良心。
    80pts:
    考虑每个联通分量中,能走的肯定要尽量去走,然后我们缩点求出连通分量的贡献,转换成DAG上的问题,然后发现DAG上不能够简单地按照拓扑序取min做dp转移,但是我们可以对DAG上每一个位置开一个64的数字记录到这个节点各个数字是否可行,然后拓扑序转移,复杂度64(N + M) 还是能跑过去的
    100pts:
    既然每个二进制位上的数字互不干扰,我们就拆分二进制做。
    考虑从高位向低位枚举二进制位,我们肯定是希望高位上能够为0,那么我们考虑在整个DAG中的那些路径是能够使这一位为0的,显然,在所有从s到t的道路中,若存在某个点或者边,那么他所有的后继路径和前驱路径都是可行的,那么我们可以正反拓扑两次找到所有可行的点边集合作为当前答案。
    然后考虑下一位,下一位中因为要保证上一位是0,所以能够走的点和边肯定是上次得到的点边集合里的,我们在这个得到的集合中在尽行同样的拓扑看看当前位是否可行,如果可行的话就用新得到的点边集合去更新原图的点边集合。
    如此做三十次考虑所有的为就能得到答案了。
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #include<ctime>
    #include<cmath>
    #include<set>
    #include<map>
    #define ll long long
    #define M 700010
    struct Edge {
        int vi, vj, v;
    } edge[M];
    struct Note {
        int vj, v, id;
    } be;
    using namespace std;
    int read() {
        int nm = 0, f = 1;
        char c = getchar();
        for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
        for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
        return nm * f;
    }
    vector<int>to[M];
    vector<Note> to1[M], to2[M];
    int belong[M], st[M], dfn[M], low[M], dft, n, m, s, t, note[M], noww[M], tp, tot, sz[M], ans = 2147483647, rudu1[M], rudu2[M];
    bool vis[M];
    void tarjan(int now) {
        vis[now] = true;
        st[++tp] = now;
        dfn[now] = low[now] = ++dft;
        for(int i = 0; i < to[now].size(); i++) {
            int vj = to[now][i];
            if(!dfn[vj]) {
                tarjan(vj);
                low[now] = min(low[now], low[vj]);
            } else if(vis[vj]) low[now] = min(low[now], dfn[vj]);
        }
        if(dfn[now] == low[now]) {
            tot++;
            while(st[tp] != now) {
                int x = st[tp];
                vis[x] = false;
                noww[tot] &= note[x];
                belong[x] = tot;
                tp--;
            }
            int x = st[tp];
            vis[x] = false;
            noww[tot] &= note[x];
            belong[x] = tot;
            tp--;
        }
    }
    bool can[M], tmp1[M], tmp2[M];
    int note1[M], note2[M], tp1, tp2;
    
    void tuopu() {
        queue<int>q;
        q.push(belong[t]);
        while(!q.empty()) {
            int op = q.front();
            q.pop();
            for(int i = 0; i < to2[op].size(); i++) {
                int vj = to2[op][i].vj;
                rudu2[vj]++;
                if(!vis[vj]) q.push(vj), vis[vj] = true;
            }
        }
        while(!q.empty()) q.pop();
        q.push(belong[s]);
        while(!q.empty()) {
            int op = q.front();
            note1[++tp1] = op;
            q.pop();
            for(int i = 0; i < to1[op].size(); i++) {
                int vj = to1[op][i].vj;
                rudu1[vj]--;
                if(rudu1[vj] == 0) q.push(vj);
            }
        }
        q.push(belong[t]);
        while(!q.empty()) {
            int op = q.front();
            q.pop();
            note2[++tp2] = op;
            for(int i = 0; i < to2[op].size(); i++) {
                int vj = to2[op][i].vj;
                rudu2[vj]--;
                if(rudu2[vj] == 0) q.push(vj);
            }
        }
    }
    
    void work(int x) {
        for(int i = 1; i <= tot; i++) tmp1[i] = tmp2[i] = false;
        if((noww[belong[s]] & x) == 0) tmp1[belong[s]] = true;
        for(int i = 1; i <= tp1; i++) {
            int op = note1[i];
            for(int j = 0; j < to1[op].size(); j++) {
                be = to1[op][j];
                if((tmp1[op] == true) || (can[be.id] && ((be.v & x) == 0))) {
                    tmp1[be.vj] = true;
                    tmp1[be.id] = true;
                } else if((noww[be.vj] & x) == 0 && (can[be.vj])) tmp1[be.vj] = true;
            }
        }
        if((noww[belong[t]] &x) == 0) tmp2[belong[t]] = true;
        for(int i = 1; i <= tp2; i++) {
            int op = note2[i];
            for(int j = 0; j < to2[op].size(); j++) {
                be = to2[op][j];
                if((tmp2[op] == true) || (can[be.id] && ((be.v & x) == 0))) {
                    tmp2[be.vj] = true;
                    tmp2[be.id] = true;
                } else if((noww[be.vj] & x) == 0 && (can[be.vj])) tmp2[be.vj] = true;
            }
        }
        for(int i = 1; i <= tot; i++) tmp1[i] = (tmp1[i] | tmp2[i]);
        if(tmp1[belong[s]] && tmp1[belong[t]]) ans -= x;
        else return;
        for(int i = 1; i <= tot; i++) can[i] = (can[i] & tmp1[i]);
    }
    int main() {
        freopen("rabbit.in", "r", stdin);
        freopen("rabbit.out", "w", stdout);
        cin >> n >> m >> s >> t;
        for(int i = 1; i <= n; i++) note[i] = read(), noww[i] = 2147483647;
        for(int i = 1; i <= m; i++) {
            int vi = read(), vj = read(), v = read();
            edge[i].vi = vi, edge[i].vj = vj, edge[i].v = v;
            to[vi].push_back(vj);
        }
        tarjan(s);
        if(!dfn[t]) {
            puts("-1");
            return 0;
        }
        for(int i = 1; i <= m; i++) {
            int vi = edge[i].vi, vj = edge[i].vj, v = edge[i].v;
            vi = belong[vi], vj = belong[vj];
            if(vi == 0 || vj == 0) continue;
            if(vi == vj) noww[vi] &= v;
            else {
                be.id = ++tot;
                be.vj = vj;
                be.v = v;
                to1[vi].push_back(be);
                rudu1[vj]++;
                be.vj = vi;
                to2[vj].push_back(be);
            }
        }
        if(belong[s] == belong[t]) {
            cout << noww[belong[s]] << "
    ";
            return 0;
        }
        tuopu();
        for(int i = 1; i <= tot; i++) can[i] = true;
        for(int i = 30; i >= 0; i--) work(1 << i);
        cout << ans << "
    ";
        return 0;
    }
    std
  • 相关阅读:
    JavaScript---网络编程(3)-Object、String、Array对象和prototype属性
    HDOJ/HDU 2087 剪花布条(indexOf()应用~~)
    HDOJ/HDU 1984 Mispelling4(删除第n个字符~)
    HDOJ/HDU 1982 Kaitou Kid
    HDOJ/HDU 1804 Deli Deli(英语单词复数形式~)
    JavaScript---网络编程(2)-函数与数组
    HDOJ/HDU 1328 IBM Minus One(水题一个,试试手)
    JavaScript---网络编程(1)-介绍、变量、运算符与语句
    HDOJ/HDU 1256 画8(绞下思维~水题)
    多栏自适应布局
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/9900984.html
Copyright © 2020-2023  润新知