傳送門
文章目錄
題意:
有nnn個時間,每個時間給你兩個操作,第一個是k=k+xk=k+xk=k+x,第二個是k=k?xk=k*xk=k?x,且可以執行[0,y][0,y][0,y]次,kkk初始狀態為000,求[1,m][1,m][1,m]中kkk能到達的數的最短時間。
思路:
首先比較容易的能想到一個nm2nm^2nm2的暴力方法,就是遍歷[1,n][1,n][1,n],讓后對于每個已經出現過的數,嘗試進行[0,y][0,y][0,y]次相應的操作,yyy的范圍[0,m][0,m][0,m]。
我們可以發現這樣更新的話,會有很多重復更新的數。
比如原本能到的數有[3,11][3,11][3,11],現在x=4,y=4x=4,y=4x=4,y=4,那么你對于每個數更新的時候遍歷到的集合就是[3,7,11,15,19][3,7,11,15,19][3,7,11,15,19]和[11,15,19,23,27][11,15,19,23,27][11,15,19,23,27],我們可以發現當333加到111111后,之后的數都會在111111的位置再次加一遍,由此可見,我們當加數的時候,如果當前數已經存在了,那么我們直接breakbreakbreak就好啦,因為之后遍歷到這個數的時候也會再次加一遍,這樣是無效的工作。
由于我們[0,m][0,m][0,m]的數最多遍歷兩次,是常數級別的,所以復雜度為O(NM)O(NM)O(NM)。
還有就是上取整的時候最好別用浮點數的ceilceilceil,容易錯。
#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
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
;
struct Node
{LL t
,x
,y
;
}a
[N
];
vector
<bool>v(N
+1,0);
int ans
[N
];int main()
{
scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
;i
++){scanf("%lld%lld%lld",&a
[i
].t
,&a
[i
].x
,&a
[i
].y
);if(a
[i
].t
==1){LL now
=(a
[i
].x
+100000-1)/100000;a
[i
].x
=now
;}}v
[0]=1;for(int i
=1;i
<=n
;i
++){auto nv
=v
;if(a
[i
].t
==1){for(int k
=0;k
<=m
;k
++){if(!v
[k
]) continue;for(int j
=1;j
<=a
[i
].y
;j
++){LL now
=1ll*j
*a
[i
].x
;if(now
>m
) break;if(now
+k
<=m
&&!v
[now
+k
]) nv
[now
+k
]=true,ans
[now
+k
]=i
;else break;}}}else if(a
[i
].t
==2){for(int k
=0;k
<=m
;k
++){if(!v
[k
]) continue;LL now
=k
;for(int j
=1;j
<=a
[i
].y
;j
++){now
=(now
*a
[i
].x
+100000-1)/100000;if(now
>m
) break;if(now
<=m
&&!v
[now
]) nv
[now
]=true,ans
[now
]=i
;else break;}}}v
=nv
;}for(int i
=1;i
<=m
;i
++) if(ans
[i
]==0) printf("-1 "); else printf("%d ",ans
[i
]);return 0;
}
總結
以上是生活随笔為你收集整理的CodeCraft-21 and Codeforces Round #711 (Div. 2) D. Bananas in a Microwave 优化暴力的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。