[NOIP模擬][狀壓DP]乘積
題目描述:
題目大意:
給出n和k,求從小於等於n的數中取出不超過k個,其乘積是無平方因子數的方案數。無平方因子數:不能被質數的平方整除。
樣例輸入:
3
1 1
6 4
4 2
樣例輸出:
1
19
6
題目大意:
狀壓dp+分組揹包:
1~n中每個數含有的大於
因為程式碼用了vector,vector呼叫比較慢,出題人又專門卡常,所以需要一些優秀的卡常技巧。
附程式碼:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=600;
const int M=(1<<8)-1;
const int mod=1e9+7;
const int prime[8]={2,3,5,7,11,13,17,19};
int f[N][M+10],num[N],exist[N],n,k,t,temp[N],ans;
vector<int> g[N];
int readint()
{
char ch;int i=0,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if (ch=='-') {ch=getchar();f=-1;}
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}
void prework()
{
for(int i=1;i<=n;i++)
{
int now=i;exist[i]=true;
for(int j=0;j<8;j++)
if(now%(prime[j]*prime[j])==0)//判斷此數是否符合是無平方因子數
{
exist[i]=false;
break;
}
else
if(now%prime[j]==0)//表示這個數含有小於等於19的質因子
now/=prime[j],num[i]|=(1<<j);//記錄狀態,包含哪些小於等於19的質因子
if(exist[i])
{
if(now==1) g[i].push_back(i);//不含大於19的質因子,單獨成組
else g[now].push_back(i); //前面每次都在除,還有剩餘,說明含大於19的質因子,於是分到質因子那組
}
}
}
void add(int &x,int t)//為了卡常
{
x+=t;
if(x>=mod) x-=mod;
}
int main()
{
//freopen("mul.in","r",stdin);
//freopen("mul.out","w",stdout);
t=readint();
while(t--)
{
n=readint();k=readint();
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++) g[i].clear();
prework();
f[0][0]=1;
for(int i=1;i<=n;i++)//其實是在列舉每一個分組
if(exist[i]&&g[i].size()!=0)//此數合法且此組不為空
{
for(int j=g[i].size()-1;j>=0;j--)//為了卡常
temp[j]=num[g[i][j]];
for(int l=k-1;l>=0;l--)//倒序,因為下面的更新,是把上一層的更新到現在的i,正序會讓這一層覆蓋掉上一層的結果
for(int j=g[i].size()-1;j>=0;j--)//列舉這一組
for(int s=(M^temp[j]),t=s;;s=((s-1)&t))//s表示狀態,第一節是指只不選temp[j],第三節是在跳s的每個子集
{
add(f[l+1][s|temp[j]],f[l][s]);//f[l][s]存的是指上一層計算出來的結果
if(s==0) break;//子集為空break,之所以不放在for迴圈第二節,是因為我們需要更新一次子集為空的轉移
}
}
ans=0;
for(int i=1;i<=k;i++)//統計各種情況和
for(int j=0;j<=M;j++)
add(ans,f[i][j]);
cout<<ans<<'\n';//printf("%d\n",ans);
}
return 0;
}
相關推薦
[NOIP模擬][狀壓DP]乘積
題目描述: 題目大意: 給出n和k,求從小於等於n的數中取出不超過k個,其乘積是無平方因子數的方案數。無平方因子數:不能被質數的平方整除。 樣例輸入: 3 1 1 6 4 4 2 樣例輸出: 1 19
不死的LYM NOIP模擬 二分+狀壓DP
gis using getchar() == cstring int algo true check 一共也就7種課,第7種可以貪心地選擇一定睡覺以換取答案的最小值。 那麽我們就只剩下六種課需要討論,狀態壓縮一下【當前的課之前睡過哪些課】即可。 本題要在二分的check
2018.10.01 NOIP模擬 偷書(狀壓dp)
傳送門 狀壓dp經典題。 令f[i][j]f[i][j]f[i][j]表示到第i個,第i−k+1i-k+1i−k+1~iii個物品的狀態是j時的最大總和。 然後簡單維護一下轉移就行了。 由於想皮一下果斷
2018.10.05 NOIP模擬 上升序列(狀壓dp)
描述 給出一個長度為 m 的上升序列 A(1 ≤ A[i]≤ n), 請你求出有多少種 1…n 的排列, 滿足 A 是它的一個 LIS. 輸入 第一行兩個整數 n,m. 接下來一行 m 個整數, 表示
2018.10.17 NOIP模擬 管道(狀壓dp)
傳送門 狀壓dp好題。 怎麼今天道道題都有點東西啊 對於今天題目神仙出題人先膜為上策:%%%%DzYoAk_UoI%%%% 設f[i][j]f[i][j]f[i][j]表示選取點的狀態集合為iii,當
11-1 noip模擬 第二題 SPFA+狀壓dp
#include #include #include #include using namespace std; struct edge{ long long y,l,z; }f[50010*2]; long long i,j,g[10010],n,m,k,t,dis[17][10010],T,d[
【題解】[牛客網NOIP賽前集訓營-提高組(第二場)]C.集合劃分 狀壓DP
題目連結 看了題解後還是沒寫對,只能去看Komachi大佬咋寫的了。 #include<cstdio> #include<cstring> const int N=18,MX=(1<<18)+5; int n,m,k,ban[N]
狀壓dp NOIP 2016 憤怒的小鳥
題意:有 n n n只豬,第
2018.10.01【校內模擬】偷書(狀壓DP)
描述 在L的書架上,有N本精彩絕倫的書籍,每本書價值不菲。 M是一個書籍愛好者,他對L的書籍早就垂涎三尺。最後他忍受不了誘惑,覺得去偷L的書,為了迅速完成這件事,同時他不希望L很快發現書籍少了,他決定偷書時,對於任意連續的k本書,他最多選B本,最少選A本。現在他
jzoj5990. 【北大2019冬令營模擬2019.1.6】Bear (狀壓dp)
題面 題解 我永遠討厭dp.jpg 搞了一個下午優化複雜度最後發現只要有一個小trick就可以A了→_→。全場都插頭dp就我一個狀壓跑得賊慢…… 不難發現我們可以狀壓,對於每一行,用狀態\(S\)表示有哪些格子是已經被上一行推倒了的,那麼我們可以列舉本行所有格子的字母情況,然後計算一下這個時候下
【狀壓DP】【NOIP提高組】憤怒的小鳥
這是道不算水的狀壓DP 這道題對我的吸引力很大,為什麼呢,因為它的背景是遊戲啊 題目描述 Kiana 最近沉迷於一款神奇的遊戲無法自拔。 簡單來說,這款遊戲是在一個平面上進行的。 有一架彈弓位於 (0,0)(0,0) 處,每次 Kiana 可以用它向第一象限發射
[模擬考試題][神題]Star Sky[狀壓DP][BFS][差分]
題意: 給你n個排成一排的燈,0代表開著,1代表關著,有k盞開著的燈。現在你有m種不同長度的電線,可以使得leni那麼長的區間反轉(0變1,1變0)。現在問你使得整個區間的燈全部開著的最少的運算元。 N <= 40000 K <= 8 M <= 64 真心
NOIP專題複習(三) 狀壓DP學習筆記
其實並不是三,已經走了很多專題了。 之後慢慢填坑吧。 我覺得學普通的DP已經救不了我了。 發覺似乎NOIP狀壓蠻裸的(flag立的飛起),於是學一波。 其實在下作為一隻蒟蒻,認為狀壓DP屬於很好理解但不太好寫的型別。 還是從經典例題互不侵犯開始。
BJ模擬 裝飾地板【狀壓dp+特徵多項式優化矩陣快速冪】
題目大意: 給一個m∗nm∗n的地板,有s1s1種1×21×2的橫地磚,s2s2種2×12×1的豎地磚,問有多少種鋪滿的方式,對998244353取模。 (m≤6,n≤102501,s1,s2≤1e9)(m≤6,n≤102501,s1,s2≤1e9)
noip 2016(憤怒的小鳥)(狀壓dp)
狀壓dp,每位代表一隻豬,1為豬打到了,0為豬還沒打到 兩個豬的座標確定一條拋弧線(即為打出鳥的軌跡) g[i][j]表示由i豬和j豬確定的拋弧線,能打到的豬。(是一個二進位制的狀態) 預處理:把能被i豬和j豬確定的這條拋弧線能打到的豬都用狀壓的1來表示,存到g[i][
【狀壓DP】poj3254 Corn Fields
一行 cstring fields while state 條件 style 狀壓 () 題意: 一塊n*m的田,1表示這個地方可以種植,0代表這個地方不能種植。植物種植還必須滿足兩株植物不能相鄰(橫豎都不行)。問共有幾種種植方法,而且當什麽都不種時認為是一種方法。 解題思
【bzoj4145】[AMPPZ2014]The Prices 狀壓dp
return std sin highlight string span 題目 狀態壓縮dp print 原文地址:http://www.cnblogs.com/GXZlegend/p/6832200.html 題目描述 你要購買m種物品各一件,一共有n家商店,你到第i家
狀壓DP入門——鋪磚塊
ont 輸出 fin load www ret mil times set 題目描述 現有n*m的一塊地板,需要用1*2的磚塊去鋪滿,中間不能留有空隙。問這樣方案有多少種 輸入 輸入n,m(1<=n, m<=11) 有多組輸入數據,以m=n=0結束
[LightOJ 1018]Brush (IV)[狀壓DP]
邊界 lightoj 計算 const 擁有 for ostream 當前 blank 題目鏈接:http://lightoj.com/volume_showproblem.php?problem=1018 題意分析:平面上有不超過N個點,如今能夠隨意方向劃直線將它們劃
SGU 223 little kings BSOJ2772 狀壓DP
而且 進制 print 剪枝 描述 計算機 tex 範圍 blog 1896 [SCOI2005]互不侵犯King 【問題描述】在n*n(1<=n<=10)的棋盤上放k(0<=k<=n*n)個國王(可攻擊相鄰的8 個格子),求使它們無法互相攻擊的方