首页 > 其他分享 >CF1981D题解

CF1981D题解

时间:2024-05-31 21:45:31浏览次数:14  
标签:le CF1981D int 题解 times 欧拉

CF1981D题解

前言

标签:筛法,欧拉回路

赛后过的,构造一眼秒,欧拉图写错了,多少有点抽象。

题意

构造一个长度为 \(n\) 的序列 \(a\),需要满足:

  • \(\forall 1 \le i \le n\),\(1 \le a_i \le 3\times10^5\)。

  • \(\forall 1 \le i<j<n\),\(a_i\times a_{i+1}\ne a_j\times a_{j+1}\)。

分析

发现任意两个质数的乘积是唯一的,而 \(\max_{1\le i\le 3\times 10^5}\{d(i)^2\} \le 10^6\)。

所以显然只需要选 \(m\) 个质数。

而现在就是要构造一个长度为 \(n\) 的序列使得每一对无序数对 \(\{a_i,a_{i+1}\}\) 都不同。

因为构造方式是从一个数开始,走到另一个数,和路径是一样的,所以考虑构造一个无向完全图(带自环),然后找最长路径。

当 \(m\) 是奇数时,每个点的度一定是偶数,所以直接跑欧拉回路,序列长度为 \(\frac{m\times (m+1)}{2}+1\)。

当 \(m\) 是偶数,每个点的度一定是奇数,我们可以删除所有形如 \(\{3,4\},\{5,6\},\dots,\{n-1,n\}\) 的边,这样就剩下了两个奇点,直接跑欧拉回路,序列长度为 \(\frac{m\times (m+1)}{2}-\frac{m-2}{2}+1\)。

直接枚举求 \(m\) 即可。

代码

建图用了 bitset

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();int x=0;bool f=1;
    while(ch<'0'||'9'<ch){if(ch=='-')f=0;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}
const int N=3e5+2;
int cnt,prime[N];
bool is_p[N];
void init(int n){
    for(int i=2;i<=n;i++){
        if(!is_p[i])prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
            is_p[i*prime[j]]=1;
            if(!(i%prime[j]))break;
        }
    }
}
const int M=1500;
int n,m;
bitset<M>vis[M];
stack<int>st;
void dfs(int u){
    if(vis[u][u])vis[u][u]=0,dfs(u);
    for(int i=vis[u]._Find_first();i<=m;i=vis[u]._Find_first())
        if(vis[u][i])
            vis[u][i]=vis[i][u]=0,dfs(i);
    st.push(prime[u]);//注意要最后加点,不然跑出来的不是欧拉回路,笔者栽在这里了
}
void Main(){
    n=read();
    if(n==1)return puts("1"),void();
    for(m=1;(m*(m+1)/2)-((m&1)?0ll:((m>>1)-1))<n-1;m++);
    for(int i=1;i<=m;i++)
        vis[i].set();
    if(!(m&1))
        for(int i=3;i<=m;i+=2)vis[i][i+1]=vis[i+1][i]=0;
    dfs(1);
    while(!st.empty()&&n)printf("%d ",st.top()),st.pop(),n--;
    while(!st.empty())st.pop();
    puts("");
    return;
}
signed main(){
    init(13000);
    int T=read();
    while(T--)Main();
    return 0;
}

标签:le,CF1981D,int,题解,times,欧拉
From: https://www.cnblogs.com/sunzz3183/p/18225312

相关文章

  • 题解合集
    CF1270FAwesomeSubstringsCF1860CGameonPermutationP10161[DTCPC2024]小方的疑惑10P10236[yLCPC2024]D.排卡P10368「LAOI-4」ColorsP10369「LAOI-4」MexTower(Easyver.)P10370「LAOI-4」MexTower(Hardver.)P2398GCDSUMP2568GCDP8445射命丸文的取材......
  • CF Round946(div3) 题解
    目录946(div3)ABCDEG946(div3)A每个屏幕3X5,可放2个2X2,其余可填7个1X1先算2X2需要多少个屏幕,再算当前屏幕是否可放下所有1X1,根据1X1的量加屏幕.voidfunc(){ inta,b; cin>>a>>b; intans=(b+1)/2; intstp=a-(ans*15-4*b); if(stp>0) ans+=(s......
  • P2215 [HAOI2007] 上升序列题解
    题目大意对于一个集合$S$,对于$S$中长度为$m$的子序列$P$,在集合$P$中如果$P_1<P_2<...<P_m$那么我们称$P$为$S$的一个上升序列。如果有多个$P$满足条件我们就输出最小的那个,如果没有完成条件的$P$则输出Impossible。思路对于一个含有$......
  • P2266 爱的供养题解
    题目大意给你一个矩阵$w$,大小为$n\timesm$,然后你每次都从一个宝藏点开始去走旁边$T-1$个点施法,施法过的点就不用再走了,施法不需要耗费体力但是每一次从一个点走到另一个点需要耗费的权值为这两个点的高度差,你每次可以走的方向是上下左右。求最小需要耗费的体力。......
  • P10526 [XJTUPC2024] 命令行题解
    题目大意对于一个字符串$s$在输入的最后一行读入的字符,如个字符不为$E\(,\)T\(,\)B$那么这一个字符就添加至字符串$s$的末尾。对于操作$B$那么执行删除字符串$s$的最后一个字符,如果$s$为空那么跳过这个操作。对于操作$T$找到一个以字符串......
  • P10530 [XJTUPC2024] 生命游戏 题解
    题目大意一棵树一共$n$个点如果有$k$个点与某一个点相连那么这一轮的结尾这个点就会死。思路这道题有几个坑!并没有说哪一个节点是根节点。双向边记得开双倍数组。等这一轮的点消除完了才能再次判断哪一些点可以消除。首先我们创建一个数组$Size_{n}$来......
  • CF/505/D 题解
    思路这道题的思路其实是根据样例图片来的。首先第一张:这张图片可以得知$n$个点没有环的时候最少需要$n-1$个点。再看第二张:这个图确实很难思考,但稍微思考一下如果我们把含有一个强连通分量的图变成一整个强连通图。这个图的边数不就变成$n$了吗?来推一下......
  • P6342 [CCO2017] Vera 与道路建设 题解
    题目大意对于一个图w一共有v个点点的编号为1,2,...,v,对于点a与点b如果满足$a\tob$且$b\toa$使得每一条道路都只走过一次,那么我们称$a,b$为完美点对,当一个联通图只有$k$个完美点对时,称这个联通图为美丽公路网,要求求出一个美丽公路网......
  • Nikita and LCM题解
    题目大意给你一个数组$a$,令$t$为$a$的子序列且$t$中所有数的最小公倍数$\notina$求$t$数组中最多有多少个数。思路非常明显这是一道数学题,对于数组$a$我们首先从小到大拍一个序,然后我们可以求出$a$中所有数的最大公倍数,如果这个公倍数$\not=......
  • MITIT 2024 Spring Invitational Qualification 简要题解
    这个比赛没有找到题解,有点难绷,所以来写篇。(实际上是无聊时写的就是了)题面:https://codeforces.com/gym/105125/。目测难度是绿绿黄紫紫。A有点诈骗。其实策略是只保留\(\le3\)个数,然后就随便维护一下。\(O(n\logn)\)。Code#include<bits/stdc++.h>usingnamespaces......