Codeforces Round #493 (Div. 1) B
阿新 • • 發佈:2018-12-24
題意:1,5,10,50四種硬幣不限量,問用剛好n個硬幣可以湊出多少種不同的數,n<=1e9
分析:本題的一大難點在於同一個數可能被不同的硬幣所表示,可以通過如下方法化簡:
由於硬幣數量固定,我們可以把所有硬幣的價值-1,使得價值變為{0,4,9,49}
考慮如果我們選了(49+x)個4或者9,可以將其換成x個4或9,將49的倍數部分用0和49進行填充
所以我們可以列舉4和9各選i,j個,i/j取[0,min(n,48)]之間且i+j<=n時可以得到的對於49的餘數
設sum = 4*i + 9*j, 剩下的位置只選擇0或49,可以在sum到sum+(n-i-j)*49之間每隔49個都能取一個
這樣對於每種49的餘數處理出最大的可行區間即可
#include<bits/stdc++.h> #define pii pair<int, int> #define fi first #define se second #define mk make_pair #define sc(x) scanf("%d", &x) #define pb push_back #define ABS(x) ((x)<0?(-x):(x)); typedef long long LL; using namespace std; const int INF = 0x3f3f3f3f; const int mod = 1e9+7; const int maxn = 1e6+10; int n, L[50], R[50]; int main(){ freopen("lych.in", "r", stdin); for(int i = 0; i < 49; i++) L[i] = INF, R[i] = -INF; sc(n); L[0] = 0; R[0] = n; for(int i = 0; i <= min(n,49); i++){ for(int j = 0; j <= min(n,49); j++){ if(i+j > n) continue; int sum = (i*4+j*9); int r = sum%49, b = sum/49; L[r] = min(L[r], b); R[r] = max(R[r], b+n-i-j); } } LL ans = 0; for(int i = 0; i < 49; i++){ if(L[i] >= INF) continue; //printf("L[%d]:%d, R[%d]:%d\n", i, L[i], i, R[i]); ans += R[i]-L[i]+1; } cout << ans << endl; return 0; }