HDU 4028 The time of a day [离散化DP]
虽然数很大,但是这40个数的公倍数一共才4万多个。这里用到STL会方便很多,map[i]里存放了从1~i能组成的公倍数有哪些以及每个数有多少种组成方法。
预处理一遍打个表然后每次O(n)的遍历一遍,否则会超时。
#include <string.h> #include <stdio.h> #include <map> typedef __int64 LL; int n,cas; LL m,ans; std::map<LL,LL> mp[41]; std::map<LL,LL>::iterator it; LL gcd(LL a,LL b){ return b==0?a:gcd(b,a%b); } //初始化,否则会超时 void init(){ for(int i=1;i<=40;i++){ for(mp[i]=mp[i-1],it=mp[i-1].begin();it!=mp[i-1].end();it++){ LL num=it->first; LL x=i*num/gcd(i,num); mp[i][x]+=it->second; } mp[i][i]++; } } int main(){ //freopen("test.in","r",stdin); scanf("%d",&cas); init(); for(int ca=1;ca<=cas;ca++){ scanf("%d%I64d",&n,&m); ans=0; for(it=mp[n].begin();it!=mp[n].end();it++){ if(it->first>=m)ans+=it->second; } printf("Case #%d: %I64d\n",ca,ans); } }