一道玄學題...
其實一開始想的是對的,優化一下就好了
首先我們會發現,乘積不能被完全平方數整除等價於所有因子的每個質因子個數和都至多為1
可是500以內的質數很多,全找出來會**的
可我們會發現,如果乙個數的平方會在500以內,那麼這個數一定<=22!
所以,1~500中會存在的完全平方數的質因子一定在22以內
這些質數只有八個,所以我們可以找出來
至於剩下的部分,顯然23和46是不嫩同時出現的,所以我們把含有23這個因子的所有數分到乙個揹包裡,對每個揹包只允許使用其中的乙個數,這樣就能滿足23等只出現一次,對其他更大的質數也是同理
什麼?你說會不會重?
23*23>500,那麼剩下所有的乘積都大於500,也就是說如果我們只用23及以上的質數分組,每組中的元素是互不重疊的。
什麼?你說前面幾個小的質數怎麼辦?
狀壓啊!
求出每個數對於前面八個質數(是的,小於23的質數有8個,分別為2,3,5,7,11,13,17,19),而言質因子的狀態,用二進位制表示(如15的質因子狀態可以表示為110,即0個2,1個3,乙個5)
至於那些用大質數表示不了的數,我們把他們每個單獨分包即可。
在轉移的時候,我們就可以第一層:列舉所有包,第二層:列舉包中每個元素,第三層:列舉前八個質數的所有狀態,第四層:列舉前面用過的數的個數
當然,我本人在寫**的時候,選擇把所有不能分到其他包裡的元素全分到第乙個包裡,然後單獨處理第乙個包。
#include #include #include #include #include #include #include #include #define ll long long
#define mode 1000000007
using namespace std;
int cnt=0;
int pri[505];
bool vis[505];
ll dp[2][(1<<8)+5][505];
int sit[505];
bool used[505];
int bag[105][505];
int cct[105];
int posi[505];
int n,k;
void init()
for(int j=0;j=pri[t];t++)
}if(!flag)
}}void get_ori()
if(cot>=2)
else if(cot==1)
} }}
int main()
}for(int j=0;j<(1<<8);j++)}}
swap(now,past);
} for(int i=2;i<=cnt-7;i++)
}for(int f=1;f<=cct[i];f++) }}
}swap(now,past);
} ll ans=0;
for(int i=0;i<(1<<8);i++)
}printf("%lld\n",ans%mode);
} return 0;
}
hdu6125 (狀態壓縮 分組揹包)
題解 因為小於根號500的質數有8個,我們可以用二進位制表示為放入的這些數已經含有前面8個質數的哪幾個然後,因為選擇1 k個數後相乘起來沒有平方因子,所以有任何能除以這前面8個質數的平方的都不可以,還有就是如果這個數把這8個質數能取餘等0的都除後等於1的話那麼這個數應該在自己這個數這一組,如果不能等...
狀壓dp 玉公尺田 狀壓dp
相關 強相關 327.玉公尺田 狀壓dp 小國王 狀壓dp 是井字形,本題是十字形。思路 狀態計算 時間複雜度 n 2 n 2n o n 22n 12 2 24n 2 n 2 n o n2 12 2 n 2n 2 n o n22n 12 224 看著妥妥超時,但是裡面合法狀態很少 依舊可以過 在此,...
hdu 檢測賽 Problem C(狀壓dp)
新年伊始,集訓隊迎來了15級新生。教練打算將大家n 2 n 20 個人分成ab兩隊,已知每兩個新生之間都有相互的思念值,如果分到一隊的話經常見面不會思念,但是如果不被分到一隊的話,他們就會無比思念對方,此時兩個人之間的思念值為f 0 f 10000 教練想知道,分隊使大家的思念值總和 即a隊的每個人...