zoukankan      html  css  js  c++  java
  • 2019.9.28 csp-s模拟测试54 反思总结

    咕咕咕的冲动如此强烈x

    T1x:

    看完题目想了想,感觉把gcd不为1的强行放在一组,看作一个连通块,最后考虑连通块之间的组合方式就可以了。

    然后维护这个连通块可以写并查集可以连边跑dfs怎么着都行…

    然而我在处理数字分解质因数这里T掉了,原因是一个很显然的优化写法我基本没怎么写过。线性筛的时候记录每个数是被哪个质数标记过的,分解一个数的时候直接处理记录下来的质数就可以。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,t;
    long long mod=1e9+7,ans,sum;
    int num[2000010],pri[2000010],cnt,vis[2000010],pre[2000010];
    int fa[200010];
    void work(){
        for(int i=2;i<=1000000;i++){
            if(!vis[i]){
                pri[++cnt]=i;
                pre[i]=i;
            }
            for(int j=1;j<=cnt&&i*pri[j]<=1000000;j++){
                vis[i*pri[j]]=1;
                pre[i*pri[j]]=pri[j];
                if(i%pri[j]==0)break;
            }
        }
    }
    long long ks(long long x,long long k){
        long long num=1;
        while(k){
            if(k&1)num=num*x%mod;
            x=x*x%mod;
            k>>=1;
        }
        return num;
    }
    int get(int x){
        if(fa[x]==x)return x;
        else return fa[x]=get(fa[x]);
    }
    int main()
    {
        scanf("%d",&t);
        work();
        while(t--){
            scanf("%d",&n);
            sum=n;
            for(int i=1;i<=cnt;i++)num[pri[i]]=0;
            for(int i=1;i<=n;i++)fa[i]=i;
            for(int i=1,x;i<=n;i++){
                scanf("%d",&x);
                
                while(x>1){
                    int y=pre[x];
                    while(x%y==0)x/=y;
                    if(!num[y])num[y]=i;
                    else{
                        int x1=get(num[y]),x2=get(i);
                        if(x1!=x2){
                            fa[x2]=x1;
                            sum--;
                        }
                        num[y]=i;
                    }
                }
                
            }
            ans=((ks(2ll,sum)%mod-2)%mod+mod)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    T2y:

    如果直接做的话,显然是从1开始,枚举路径状态,看看这个状态能达到的节点有哪些,并根据这些节点所连的边能达到的点的集合拓展下一位的状态。最后看长度为d的状态有多少个所能到达的点的集合不为空,统计答案。

    但是这样要枚举的状态太多了。

    于是考虑把路径拆成两部分,对每个点都求一次能达到的路径的答案,存下每个长度为d的一半的路径状态能达到哪些点。可以倒序从n开始求,最后一次求的就正好是1能达到的一半路径的状态。枚举前后两半的路径状态,若两者存在交集,即两半路径存在可以相连的中间点,那么答案+1。

    #include<iostream>
    #include<cstdio>
    #include<bitset>
    using namespace std;
    int n,m,d,x1,x2,ans;
    bitset<110>sum0[110],sum1[110],f[1<<11],g[1<<11];
    //void add(int x,int y,int z){
    //    ver[++tot]=y;
    //    Next[tot]=head[x];
    //    head[x]=tot;
    //    edge[tot]=z;
    //}
    int main()
    {
        scanf("%d%d%d",&n,&m,&d);
        x1=d/2,x2=d-x1;
        for(int i=1,x,y,z;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            if(z){
                sum1[x][y]=1;
                sum1[y][x]=1;
            }
            else{
                sum0[x][y]=1;
                sum0[y][x]=1;
            }
        }
        for(int i=n;i>=1;i--){
            for(int j=0;j<(1<<11);j++)f[j].reset();
            f[1][i]=1;
            for(int j=1;j<(1<<x2);j++){
                for(int k=1;k<=n;k++){
                    if(f[j][k]){
                        f[j<<1]|=sum0[k];
                        f[j<<1|1]|=sum1[k];
                    }
                }
            }
            for(int j=0;j<(1<<x2);j++){
                g[j][i]=f[(1<<x2)|j].any();
            }
        }
        for(int i=0;i<(1<<x2);i++){
            for(int j=0;j<(1<<x1);j++){
                if((g[i]&f[(1<<x1)|j]).any())ans++;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    T3z:

    强行模拟这个过程是可以骗到分的,虽然我没骗到多少…

    然而正解好像是个更难写的模拟…

    首先观察n个任务,发现如果有任务与上一个相同,或者处在上一个任务到下一个任务的路径上,那么这个任务可以忽略不计。简化以后的任务序列就成为了一左一右的过程,每一次线段平移都与上一次走相反方向。

    然后可以用链表串起这些有效任务,在询问线段长度小于最小的两个任务间距的时候,答案是一个一次函数。如果有两个任务之间的距离小于询问线段的长度,就合并相连的三个位移,答案还是一个一次函数。

    然而并不会写,虽然刚刚重新下载题解的时候好像看到发标程了…

    垃圾选手什么都菜,被赶了出来【大雾】

  • 相关阅读:
    聊聊WS-Federation
    用双十一的故事串起碎片的网络协议(上)
    责任链模式的使用-Netty ChannelPipeline和Mina IoFilterChain分析
    最小化局部边际的合并聚类算法(中篇)
    最小化局部边际的合并聚类算法(上篇)
    UVaLive 7371 Triangle (水题,判矩形)
    UVaLive 7372 Excellence (水题,贪心)
    POJ 3312 Mahershalalhashbaz, Nebuchadnezzar, and Billy Bob Benjamin Go to the Regionals (水题,贪心)
    UVa 1252 Twenty Questions (状压DP+记忆化搜索)
    UVa 10817 Headmaster's Headache (状压DP+记忆化搜索)
  • 原文地址:https://www.cnblogs.com/chloris/p/11614771.html
Copyright © 2011-2022 走看看