1. 程式人生 > >HDU 4028 The time of a day (dp+離散化)

HDU 4028 The time of a day (dp+離散化)

題意:給你1~n的數字,問你一個集合中的lcm大於m的集合有多少個

思路:這個題挺有意思的,我們直接的可以想到爆枚的話的複雜度有2^40,但是這些數中的lcm的答案缺不會有很多,最多也就是這40個數的lcm,所以不會有很大,那這樣的話我們用一個map來記錄dp[i]代表當前是有前i個數,對於每i個數的map<i,j>,我們定義lcm為i的有j個,這樣我們就可以轉移了

程式碼:

#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
typedef 
long long LL; LL gcd(LL a,LL b){ return b==0?a:gcd(b,a%b); } LL lcm(LL a, LL b){ return a*b/gcd(a,b); } map<LL,LL> dp[45]; map<LL,LL>::iterator it; void init() { dp[1][1]=1; for(int i=2;i<=40;i++){ dp[i]=dp[i-1]; dp[i][i]+=1; for
(it=dp[i-1].begin();it!=dp[i-1].end();it++){ LL as=lcm(it->first,i); dp[i][as]+=it->second; } } } int main() { init(); int T,t; scanf("%d",&T); int cas=1; while(T--){ int n;LL m; scanf("%d%lld",&n,&m); printf(
"Case #%d: ",cas++); LL ans=0; for(it=dp[n].begin();it!=dp[n].end();it++){ if(it->first>=m)ans+=it->second; } printf("%lld\n",ans); } return 0; }