[USACO09MAR]Moon Mooing

嘟嘟嘟

 

某谷的翻译挺迷的,简单来说就是给一个初值c,然后有两个函数f1 = a1 * x / d1 + b1, f2 = a2 * x / d2 + b2.把c分别带进去,所得的结果也递归带进去,这样的到一串数,输出第n小的。

 

这道题如果都带进去,然后在排序肯定行不通,因为这一串数不是递增的,不能确定后面多少有比当前数小的。

那或许会想到,可以用一个优先队列维护最小值,这样就避免排序啦。然而数据是4e6,O(nlogn)够强能过啊。

其实没那么难,完全可以用一个普通队列实现这个功能。首先我们建两个指针f1, f2,分别代表该函数该算序列中的哪一个数了。然后得出的x, y取最小值作为本次的答案放到末尾。因为选的是当前最小值,而且f(x) > x,所以可以保证这个队列一定是单调递增的。然后如果f1得出本次的答案,就f1++。

需要注意的是,指针向后移动不能写一个 if 然后else,因为如果两个函数计算出相同的值,应该都向后移动。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<vector>
 8 #include<queue>
 9 #include<stack>
10 #include<cctype>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const db eps = 1e-8;
19 const int maxn = 4e6 + 5;
20 inline ll read()
21 {
22     ll ans = 0;
23     char ch = getchar(), last = ' ';
24     while(!isdigit(ch)) last = ch, ch = getchar();
25     while(isdigit(ch)) ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
26     if(last == '-') ans = -ans;
27     return ans;
28 }
29 inline void write(ll x)
30 { 
31     if(x < 0) putchar('-'), x = -x;
32     if(x >= 10) write(x / 10);
33     putchar(x % 10 + '0');
34 }
35 
36 int c, n, a1, b1, d1, a2, b2, d2;
37 int f1 = 1, f2 = 1;
38 ll a[maxn];
39 
40 int main()
41 {
42     c = read(); n = read();
43     a1 = read(); b1 = read(); d1 = read(); a2 = read(); b2 = read(); d2 = read();
44     a[1] = c;
45     for(int i = 2; i <= n; ++i)
46     {
47         ull x = min(a1 * a[f1] / d1 + b1, a2 * a[f2] / d2 + b2);
48         a[i] = x;
49         if(x == a1 * a[f1] / d1 + b1) f1++;
50         if(x == a2 * a[f2] / d2 + b2) f2++;
51     }
52     write(a[n]); enter;
53     return 0;
54 }
View Code

 

posted @ 2018-08-24 21:28  mrclr  阅读(271)  评论(0编辑  收藏  举报