D题循环节题解:首先发现对于每个p[i],给出X后,怎么求最小周期T,即找到T满足对于序列图片说明 对任意j都有图片说明 ,不难发现图片说明
然后题目中又有T必须是质数的幂次的限制,根据式子可以发现,如果设图片说明 那么x在p1...ps上的指数最多只有一个小于p[i]相应的指数
现在问题转化为了n个数p1...pn要找到一个x使得对任意1<=i<=n,p[i]和x最多只有一个质因子的指数p[i]大于x
然后我们发现图片说明 也就是最多只有7个不同的质数相乘≤10^6,又n<=16,也就是总共最多只有112个质因子,2^16=65536,那么就可以设dp[i][s]表示处理到第i个质因子,当前s状态的数已经有一个质因子的指数大于x的指数的最小的x是多少,但是我们发现x的上限非常大,有(10^6)^16=10^96那么大,所以我们就设dp[i][s]表示成log(x)的最小值,原本转移是乘法现在就是加法,这样上限就只有log(10^96)那么大了。
预处理转移ns[i][j]表示第i个质因子指数是j,对应ns[i][j]状态的数在第i个质因子上指数大于j,转移考虑枚举第i个质因子的指数j,因为预处理了ns[i][j]就可以直接转移了,时间复杂度图片说明

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;

const int M=1000005;
const int N=115;
const int S=(1<<16)+5;
const int mod=998244353;
const double inf=1000000000000000.0;
const double eps=1e-6;

int n,sz,tot,cnt,ans;
double mn;
bool vis[M];
int pri[M],p[N],b[N],f[N][S],c[N][N],ns[N][20];
double dp[N][S];
vector<int> d[N],r[N];

void getprime(int n){
    tot=0;
    vis[1]=1;
    for (int i=2;i<=n;i++){
        if (!vis[i]) pri[++tot]=i;
        for (int j=1;j<=tot;j++){
            if (i*pri[j]>n) break;
            vis[i*pri[j]]=true;
            if (i%pri[j]==0) break;
         }
    }
}

void init(){
    for (int i=1;i<=n;i++){
        int now=p[i],t=0;
        for (int j=1;j<=tot&&pri[j]<=now;j++) if (now%pri[j]==0){
            d[i].push_back(pri[j]);
            b[++cnt]=pri[j];
            r[i].push_back(0);
            while (now%pri[j]==0){
                now/=pri[j];
                r[i][t]++;
            }
            t++;
        }
    }
    sort(b+1,b+1+cnt);
    cnt=unique(b+1,b+1+cnt)-b-1;
    for (int i=1;i<=n;i++){
        for (int j=0;j<d[i].size();j++){
            int now=d[i][j];
            now=lower_bound(b+1,b+1+cnt,now)-b;
            c[i][now]=r[i][j];
        }
    }
    for (int i=1;i<=cnt;i++){
        int sum=1;
        for (int j=0;j<=19;j++){
            int s=0;
            for (int k=1;k<=n;k++)
                if (c[k][i]>j) s|=(1<<k-1);
            ns[i][j]=s;
            sum=sum*b[i];
            if (sum>1000000) break;
        }
    }
}

int main(){
    getprime(1000000);
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&p[i]);
    sz=(1<<n)-1;
    init();
    memset(f,-1,sizeof(f));
    f[0][0]=1;
    for (int i=0;i<=cnt;i++)
        for (int s=0;s<=sz;s++) dp[i][s]=inf;
    dp[0][0]=0.0;
    for (int i=0;i<cnt;i++){
        for (int s=0;s<=sz;s++) if (f[i][s]!=-1){
            int sum=1;
            for (int j=0;j<=19;j++){
                if ((ns[i+1][j]&s)==0){
                    int ss=s|ns[i+1][j];
                    if (dp[i][s]+log(sum)<dp[i+1][ss]){
                        dp[i+1][ss]=dp[i][s]+log(sum);
                        f[i+1][ss]=1ll*f[i][s]*sum%mod;
                    }
                }
                sum=sum*b[i+1];
                if (sum>1000000) break;
            }
        }
    }
    ans=0; mn=inf;
    for (int i=0;i<=sz;i++) if (dp[cnt][i]<mn){
        mn=dp[cnt][i];
        ans=f[cnt][i];
    }
    printf("%d\n",ans);
    return 0;
}