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

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

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

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

  • 相关阅读:
    【LeetCode-动态规划】编辑代价
    【C++】使用istringstream分割字符串
    【LeetCode-字符串】简化路径
    【LeetCode-字符串】简化路径
    【LeetCode-并查集】朋友圈
    【LeetCode-背包】目标和
    【LeetCode-动态规划】分割等和子集
    The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes
    【错误解决】本地计算机上的mysql服务启动停止后,某些服务在未由其他服务或程序使用时将自动停止
    MySQL解压版安装配置详解
  • 原文地址:https://www.cnblogs.com/chloris/p/11614771.html
Copyright © 2011-2022 走看看