素数环
  • 板块学术版
  • 楼主封禁用户
  • 当前回复7
  • 已保存回复7
  • 发布时间2025/1/15 19:18
  • 上次更新2025/1/29 17:10:52
查看原帖
素数环
1430277
封禁用户楼主2025/1/15 19:18

禁止废话!!!

f(x)=limx0xsinx f(x)=\lim_{x \to 0 }\frac{x}{\sin x}

求f(2.35997887675273e+58043)=?

好了,言归正传,本蒟蒻的括号运算已经是最优化,若还有问题或者优化,请在评论区提出,本蒟蒻会尽快出升级版,接下来我们谈一谈素数环

素数环是什么?想象一下,你老板闲的没事干,给你安排了亿点加班工作:10.你面前有一个n个孔的环,有1~n的自然数,1是 固定 的,把n-1个自然填到环里,使相邻两个数之和为素数,如果你干掉了,就涨工资!

好,我们来看一下:

什么?枚举?不行!!扣工资!!! 时间复杂度是 O(n!)O(n!) 12就已经卡顿了,16更不可能出结果

#include<iostream>
#include<algorithm>

using namespace std;

int A[100], isp[100], n;//isp是素数表,用于存放素数 

int is_prime(int x){
    for(int i = 2; i < x; i++){
        if(x % i == 0) return 0;
    }
    return 1;
}

void printPrime(){
    //生成第一个排列,顺序排列, A[1] = 1 A[2] = 2 
    for(int i = 1; i <= n; i++){
        A[i] = i;
    }
    do{
        bool ok = true;
        for(int i = 1; i < n; i++){
            int index = A[i]+A[i+1];
            if(!isp[index]){
                ok = false;
                break;
            }
        }
        //第一个和最后一个数的和 
        if(!isp[A[1] + A[n]]){
            ok = false;
        }
        if(ok){
            cout << "当前结果"; 
            for(int i = 1; i <= n; i++){
                cout << A[i] << " ";
            }
            cout << endl;
        }
    } while(next_permutation(A+2, A+n+1));//第一个一定为1不变,只更新第2个到最后1个的排列
}  

int main(){
    cin >> n;
    //记录1~n*2的值是否为素数 
    for(int i = 2; i <= n*2; i++){
        isp[i] = is_prime(i);
    }
    printPrime();
}

好,我们用回溯法:

上图片!

回溯树

#include<iostream>
#include<algorithm>

using namespace std;

int A[100], isp[100], vis[100], n;//isp是素数表,用于存放素数 

int is_prime(int x){
    for(int i = 2; i < x; i++){
        if(x % i == 0) return 0;
    }
    return 1;
}

void dfs(int cur){
    if(cur == n && isp[A[0] + A[n-1]]){//还要测试环的头尾之和是否为素数 
        for(int i = 0; i < n; i++){
            cout << A[i] << " ";
        } 
        cout << endl;
    }else{
        for(int i = 2; i <= n; i++){//第一个位置值为1,循环测试1和 2-6某个数的和是否为素数 
            /*isp[i+A[cur-1]]是剪枝函数,
              假如A[cur-1] = 1, i=3,此时之和不为素数,则把该支点剪掉,不往该子树递归
              相比于直接枚举,回溯法思想便体现在此 
            */
            if(!vis[i] && isp[i+A[cur-1]]){
                A[cur] = i;
                vis[i] = 1;//当前i的值已经放在了cur的位置,当其它层次的递归遍历到值i时,避免重复 
                dfs(cur+1);
                //要复位
                vis[i] = 0;
                A[cur] = 0; 
            } 
        }
    }
}

int main(){
    cin >> n;
    for(int i = 2; i <= n*2; i++){
        isp[i] = is_prime(i);
    }
    A[0] = 1;
    dfs(1); 
}
2025/1/15 19:18
加载中...