生活随笔
收集整理的這篇文章主要介紹了
E2. Square-free division (hard version) dp + 质因子分解
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
傳送門
文章目錄
題意:
給你長度為nnn的數(shù)組,讓后最多修改其中kkk個(gè)數(shù)(可以修改為任意數(shù)),讓后問你分成的最少組是多少。這個(gè)組內(nèi)元素是連續(xù)的且不存在任意兩個(gè)數(shù)的積為平方數(shù)。
思路:
首先兩個(gè)數(shù)之積為平方數(shù)的等價(jià)條件是兩個(gè)數(shù)的p1k1mod2p2k2mod2...pnknmod2p_1^{k_1\bmod 2}p_2^{k_2\bmod 2}...p_n^{k_n\bmod 2}p1k1?mod2?p2k2?mod2?...pnkn?mod2?相等,所以我們直接把aaa輸入的時(shí)候預(yù)處理一下就好了。
所以對(duì)于easyeasyeasy版本無修改的直接從頭開始求,讓后用一個(gè)數(shù)組記一下是否出現(xiàn)過,進(jìn)行分段即可。
對(duì)于hardhardhard版本帶修改操作的話,就不能這么貪了,可以考慮dpdpdp進(jìn)行轉(zhuǎn)移。怎么樣才能很快的找到從哪個(gè)狀態(tài)轉(zhuǎn)移是一個(gè)很大的問題,我們可以預(yù)處理一個(gè)left[i][j]left[i][j]left[i][j]數(shù)組表示最多修改jjj次,使得能從iii往前延伸的最長能到的下標(biāo),記作lll,也就是al,al+1,...,aia_l,a_{l+1},...,a_ial?,al+1?,...,ai?在修改jjj以內(nèi)都是不同的數(shù),讓后記dp[i][j]dp[i][j]dp[i][j]表示前iii個(gè)修改jjj次分得的最小段數(shù),轉(zhuǎn)移方程也就比較好寫了:dp[i][j]=min(dp[i][j],dp[left[i][x]?1][j?x]+1)dp[i][j]=min(dp[i][j],dp[left[i][x]-1][j-x]+1)dp[i][j]=min(dp[i][j],dp[left[i][x]?1][j?x]+1)
復(fù)雜度O(nk2)O(nk^2)O(nk2)。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=200010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,k
,a
[N
];
int lt
[N
][30];
int dp
[N
][30];
int st
[N
*50],nt
[N
*50];
int mp
[N
*50];
vector
<PII
>v
;int divide(int x
)
{v
.clear();while(x
!=1){int cnt
=0,div
=nt
[x
];while(x
!=1&&x
%div
==0) cnt
++,x
/=div
;v
.pb({div
,cnt
});}int ans
=1;for(auto x
:v
) if(x
.Y
%2==1) ans
=ans
*x
.X
;return ans
;
}template <class T>
bool read(T
&ret
)
{char c
;int sgn
;T bit
=0.1;if(c
=getchar(), c
==EOF)return 0;while(c
!='-' && c
!='.' && (c
<'0' || c
>'9'))c
=getchar();sgn
=(c
=='-')? -1:1;ret
=(c
=='-')? 0:(c
-'0');while(c
=getchar(), c
>='0' && c
<='9')ret
=ret
*10+(c
-'0');if(c
==' ' || c
=='\n'){ret
*=sgn
;return 1;}while(c
=getchar(), c
>='0' && c
<='9')ret
+=(c
-'0')*bit
, bit
/=10;ret
*=sgn
;return 1;
}inline void out(int x
)
{if(x
>9)out(x
/10);putchar(x
%10+'0');
}void check(int x
)
{if(x
>1e8){puts("-1");exit(0);}
}int main()
{
for(int i
=2;i
<N
*50;i
++)if(!st
[i
]){nt
[i
]=i
;for(int j
=i
+i
;j
<N
*50;j
+=i
)st
[j
]=1,nt
[j
]=i
;}int _
; read(_
);while(_
--){scanf("%d%d",&n
,&k
);for(int i
=1;i
<=n
;i
++){int x
; scanf("%d",&x
);x
=divide(x
); a
[i
]=x
;}int ct
=0;for(int j
=0;j
<=k
;j
++){int cnt
=j
;for(int i
=1;i
<=n
;i
++) mp
[a
[i
]]=0;for(int l
=1,r
=1;r
<=n
;r
++){if(mp
[a
[r
]]){mp
[a
[r
]]++;while(!cnt
){mp
[a
[l
]]--;if(mp
[a
[l
]]>=1) cnt
++;l
++;ct
++;check(ct
);}cnt
--;lt
[r
][j
]=l
;}else{ct
++;mp
[a
[r
]]++;lt
[r
][j
]=l
;check(ct
);}}}for(int i
=1;i
<=n
;i
++) for(int j
=0;j
<=k
;j
++) dp
[i
][j
]=INF
;for(int i
=1;i
<=n
;i
++){for(int j
=0;j
<=k
;j
++){for(int kk
=0;kk
<=j
;kk
++)dp
[i
][j
]=min(dp
[i
][j
],dp
[lt
[i
][kk
]-1][j
-kk
]+1);}}int ans
=INF
;for(int j
=0;j
<=k
;j
++) ans
=min(ans
,dp
[n
][j
]);printf("%d\n",ans
);}return 0;
}
總結(jié)
以上是生活随笔為你收集整理的E2. Square-free division (hard version) dp + 质因子分解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。