• 【CF772C】Vulnerable Kerbals


    题目

    题目链接:https://codeforces.com/problemset/problem/772/C
    给出 (m,n),再给一个 (m) 个数的集合让你构造一个序列满足以下的条件:

    1. 这个序列的所有数都在 (0sim m-1) 之间。
    2. 这个数列的所有前缀积取模 (m) 都不同。
    3. 所有的前缀积取模 (m) 都不能出现在给你的集合中。
    4. 最大化这个序列的长度。

    输出任意满足条件的序列。
    (nleq 2 imes 10^5)

    思路

    首先如果 (0) 没有出现在集合中,那么一定会放在序列的最后一位,接下来考虑 (1sim m-1)
    根据裴蜀定理,若前缀积为 (x),那么再添加一个数字进去,前缀积只可能是 (gcd(x,m)) 的倍数。
    一个 (O(m^2)) 的做法是如果 (gcd(x,m)|y),那么就从 (x)(y) 连一条边。然后在不经过集合内数字的前提下,最大化路径长度。
    观察到其实有很多数字下一步能到达的点是重复的。考虑吧所有 (gcd(x,m)) 相同的点缩起来,这样一个新点 (d) 表示 (gcd(x,m)=d) 的所有数,显然这些数字是可以互相到达的,所以点 (d) 的权值就是满足条件的 (x) 的数量。然后点 (d) 只需要向 (d) 的倍数连边就行了。
    这样的话图就被缩成了一张 DAG。直接跑 dp,记录前驱,最后 exgcd 求一下序列就好了。
    时间复杂度 (O(mlog m))

    代码

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    
    const int N=200010;
    int n,m,cnt[N],f[N],pre[N];
    bool used[N];
    vector<int> d[N];
    
    int exgcd(int a,int b,int &x,int &y)
    {
    	if (!b) { x=1; y=0; return a; }
    	int d=exgcd(b,a%b,x,y),t=y;
    	y=x-(a/b)*y; x=t;
    	return d;
    }
    
    int print(int n)
    {
    	if (n==-1) return 1;
    	int a=print(pre[n]);
    	for (int i=0;i<(int)d[n].size();i++)
    	{
    		int b=d[n][i],x,y,d=exgcd(a,m,x,y);
    		cout<<((b/d*x)%m+m)%m<<" "; a=b;
    	}
    	return a;
    }
    
    signed main()
    {
    	scanf("%lld%lld",&n,&m);
    	for (int i=1,x;i<=n;i++)
    		scanf("%lld",&x),used[x]=1;
    	for (int i=1,x,y;i<m;i++)
    		if (!used[i])
    		{
    			int k=exgcd(i,m,x,y);
    			cnt[k]++; d[k].push_back(i);
    		}
    	memset(pre,-1,sizeof(pre));
    	for (int i=1;i<m;i++)
    	{
    		f[i]+=cnt[i];
    		for (int j=i*2;j<m;j+=i)
    			if (f[j]<f[i]) f[j]=f[i],pre[j]=i;
    	}
    	n=1;
    	for (int i=1;i<m;i++)
    		if (f[i]>f[n]) n=i;
    	cout<<f[n]+(!used[0])<<"
    ";
    	print(n);
    	if (!used[0]) putchar(48);
    	return 0;
    }
    
  • 相关阅读:
    【转帖】电阻电容的封装
    FT2232H的MCU Host Bus Emulation 模式
    google cpp style guide
    CY7C131 BUSY信号线的接法
    有关沟通的常识
    关于for和foreach,兼顾效率与安全
    绩效面谈中处理分歧的小窍门
    SQL 合并列值和拆分列值
    如何保护.net中的dll文件(防止破解、反编译dll)(转)
    .NET框架图解之五:System.Reflection
  • 原文地址:https://www.cnblogs.com/stoorz/p/15464355.html
Copyright © 2020-2023  润新知