zoukankan      html  css  js  c++  java
  • Prime Swaps 题解

    题意:

    给出长度为 (N) 的排列,每次你可以选择两个位置 (i)(j) 并交换上边的数,前提是 (j - i + 1) 是质数。

    要求在 (5N) 次操作内,把这个序列排号,输出具体排列的操作。

    题解:

    哥德巴赫猜想: 任意大于二的偶数,都可表示成两个素数之和。

    那么我们每次放心的移动就好了!

    那我们贪心的按照 (1, 2, 3, 4……) 的顺序来排,(就是让 (1) 到第一位置,(2) 到第二位置),哥德巴赫猜想保证了我们每次都可以移得动。

    每次我们把一个数往前移动 (x) 距离时,每步先移动一个尽量大的质数距离即可。

    然后由于 (n) 以内的质数的个数为 (pi(n) sim frac{n}{ln(n)}) 个,质数间的平均间距为 (ln(n)),所以可以保证在 (5N) 次一定可以完成。

    代码中预处理哪些数是质数,以及每个数比它小的最大质数是多少。

    /*
    Date:2021.8.21
    Source:CF432C
    konwledge:哥德巴赫猜想:任意大于二的偶数,都可表示成两个素数之和。
    */
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <map>
    #define orz cout << "AK IOI"
    
    using namespace std;
    const int maxn = 1e5 + 10;
    
    inline int read()
    {
    	int f = 0, x = 0; char ch = getchar();
    	while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
    	return f ? -x : x;
    }
    inline void print(int X)
    {
    	if(X < 0) {X = ~(X - 1); putchar('-');}
    	if(X > 9) print(X / 10);
    	putchar(X % 10 + '0');
    }
    int n, a[maxn];
    map<int, int> m;
    int cnt, flag[maxn];
    bool vis[maxn], prime[maxn];
    vector<pair<int, int> > ans;
    void init()
    {
    	prime[1] = 1;
    	for(int i = 2; i <= maxn; i++) 
    	{
    		if(!vis[i]) 
    		{
    			prime[i] = 1;
    			for(int j = i; j <= maxn; j += i) vis[j] = 1;
    		}
    	}
    	for(int i = 2; i <= maxn; i++)
    		if(prime[i]) flag[i] = i;
    		else flag[i] = flag[i - 1];
    }
    int main()
    {
    	//freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        n = read();
        init();
        for(int i = 1; i <= n; i++) 
        	a[i] = read(), m[a[i]] = i;
    	for(int i = 1; i <= n; i++)
    	{
    		while(m[i] != i)
    		{
    			int t = m[i] - i + 1;                  //需要移动的距离 
    			int step = m[i] - flag[t] + 1;         //flag[t] 小于需要移动的距离的最大的质数 
    			ans.push_back(make_pair(step, m[i]));
    			m[a[step]] = m[i];                     //交换 
    			swap(a[m[i]], a[step]);
    			m[i] = step;
    		}
    	} 
        printf("%d
    ", ans.size());
        for(int i = 0; i < ans.size(); i++)
        printf("%d %d
    ", ans[i].first, ans[i].second);
    	return 0;
    }
    

    感谢 https://lhn.blog.luogu.org/solution-cf432c

  • 相关阅读:
    软件架构——”淘宝网”质量属性研究
    漫谈架构——读后感
    问题账户需求分析
    关于《软件需求分析》需要掌握哪些必要的内容的总结与思考------读后感
    人月神话阅读笔记4
    **系统项目目标文档
    人月神话阅读笔记3
    人月神话阅读笔记2
    人月神话阅读笔记1
    问题账户需求分析
  • 原文地址:https://www.cnblogs.com/yangchengcheng/p/15367853.html
Copyright © 2011-2022 走看看