Codeforces Round #259 (Div. 2) D Little Pony and Harmony Chest

来源:互联网 发布:淘宝店铺经常换ip 编辑:程序博客网 时间:2024/05/12 23:52

(比赛的时候全去想C了....

预处理状压出每一个数的因数,然后用两数的状态相加与或 是非相同来判断是否互质

暴力枚举每一个数,记录出每一个状态最小的绝对值以及该位置的数

f[ i ][ 1<<j ] 前者表示第几位,后者表示状态,值表示在 绝对值的最小和

取n为最小绝对值的状态,再逆着找在数

</pre><pre name="code" class="cpp">#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define eps 1e-9#define INF 0x3f3f3f3fusing namespace std;typedef long long ll;typedef long double ld;typedef pair<ll, ll> pll;typedef complex<ld> point;typedef pair<int, int> pii;typedef pair<pii, int> piii;template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;}template <class T>inline void write(T n){    if(n < 0)    {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n)    {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);}//-----------------------------------const int MAXN=111;int bin[20]={1};int n,cnt,m,ans=0;;int f[MAXN][1<<16],num[105][1<<16];int v[MAXN],q[MAXN],a[60];int prime[50]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};inline int cal(int x){    int sum=0;    for(int i=0;i<16;i++)        if(x%prime[i]==0)sum|=bin[i];    return sum;}void init(){for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;//状压     for(int i=1;i<59;i++)a[i]=cal(i);       //状压因数     memset(f,-1,sizeof(f));    m=(1<<16)-1;    f[0][0]=0;}int main(){init();    read(n);    for(int i=1;i<=n;i++)read(v[i]);    for(int i=0;i<n;i++)        for(int j=0;j<=ed;j++)            if(f[i][j]!=-1)                for(int k=1;k<59;k++)                {                    int to=j+a[k],t=f[i][j]+abs(k-v[i+1]);                    if((j|a[k])==to&&(t<f[i+1][to]||f[i+1][to]==-1))//公约数为 1 且绝对值最小                     {                        f[i+1][to]=t;                        num[i+1][to]=k;                    }                }    int minn=INF,po=0;    for(int i=0;i<=m;i++)        if(f[n][i]!=-1&&f[n][i]<minn)        {            po=i;minn=f[n][i];        }    for(int i=n;i>0;po-=a[q[i--]])        q[i]=num[i][po];    for(int i=1;i<=n;i++)        printf("%d ",q[i]);    return 0;}


0 0
原创粉丝点击