Educational Codeforces Round 16 D&E.

D. Two Arithmetic Progressions
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given two arithmetic progressions: a1k + b1 and a2l + b2. Find the number of integers x such that L ≤ x ≤ R and x = a1k' + b1 = a2l' + b2, for some integers k', l' ≥ 0.

Input

The only line contains six integers a1, b1, a2, b2, L, R (0 < a1, a2 ≤ 2·109,  - 2·109 ≤ b1, b2, L, R ≤ 2·109, L ≤ R).

Output

Print the desired number of integers x.

Examples
input
2 0 3 3 5 21
output
3
input
2 4 3 0 6 17
output
2

不要做这道有毒的题,这道题只有35个人做出来,E却有接近1k,可见这题有多恶心

首先推一下式子

$ x = a_{1}k+b_{1} = a_{2}l+b_{2} $

$ a_{1}k-a_{2}l = b_{2} - b_{1} $

拓展欧几里得解出一组k,l,然后就是求满足范围的k,l组数有多少个

我们知道对于一组合法的k,l,$ k+t*a_{2}/gcd(a_{1},a_{2}), l+t*a_{1}/gcd(a_{1},a_{2}) $ 也是一组合法的解,于是我们可以二分一下t的合法范围

同时由于k,l要大于0,这也对t提出了一个限制,同时处理一下这个范围,取个交集即可

然后开始出问题

1、long long会各种溢出,而且一开始算初始解的时候就会,解决方法:一开始算初始解的时候取一组小一点的解,中间一旦溢出就认为算出了无穷大,直接讨论判断合不合法(这个是不能严格证明正确性的)

2、这个范围是一个不合法---合法---不合法的东西,二分不是很靠谱,解决方法:无视之,第二种限制只二分左端点

交了大概15次

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <string>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <map>
  9 #include <stack>
 10 #include <set>
 11 #include <vector>
 12 #include <queue>
 13 #include <time.h>
 14 #define eps 1e-7
 15 #define INF 0x3f3f3f3f
 16 #define LINF 0x3f3f3f3f3f3f3f3f
 17 #define MOD 1000000007
 18 #define rep0(j,n) for(int j=0;j<n;++j)
 19 #define rep1(j,n) for(int j=1;j<=n;++j)
 20 #define pb push_back
 21 #define set0(n) memset(n,0,sizeof(n))
 22 #define ll long long
 23 #define ull unsigned long long
 24 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
 25 #define print_runtime printf("Running time:%.3lfs
",double(clock())/1000.0)
 26 #define TO(j) printf(#j": %lld
",j)
 27 //#define OJ
 28 using namespace std;
 29 const int MAXINT = 100010;
 30 const int MAXNODE = 100010;
 31 const int MAXEDGE = 2 * MAXNODE;
 32 char BUF, *buf;
 33 int read() {
 34     char c = getchar(); int f = 1, x = 0;
 35     while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); }
 36     while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
 37     return f * x;
 38 }
 39 char get_ch() {
 40     char c = getchar();
 41     while (!isalpha(c)) c = getchar();
 42     return c;
 43 }
 44 //------------------- Head Files ----------------------//
 45 ll a1, b1, a2, b2, l, r;
 46 ll exgcd(ll a, ll b, ll &x, ll &y) {
 47     if (b == 0) {
 48         x = 1; y = 0;
 49         return a;
 50     }
 51     ll ret = exgcd(b, a % b, x, y);
 52     int t = x;
 53     x = y;
 54     y = t - a / b * y;
 55     return ret;
 56 }
 57 void get_input();
 58 void work();
 59 int main() {
 60     get_input();
 61     work();
 62     return 0;
 63 }
 64 void work() {
 65     ll x, y, c = b2 - b1, v, lb, rb, ansl, ansr, mid;
 66     ll gcd = exgcd(a1, a2, x, y);
 67     if (c%gcd != 0) { printf("0
"); return; }
 68     ll lcm = a1*a2 / gcd;
 69     x *= c / gcd;
 70     ll t = x / (a2 / gcd);
 71     x %= a2 / gcd;
 72     y *= -c / gcd;
 73     y -= t* (a1 / gcd);
 74     //x=abs(x);y=abs(y);
 75     v = x*a1 + b1;
 76     /*TO(x);
 77     TO(y);
 78     TO(lcm);
 79     TO(v);*/
 80     lb = -INF * 5ll, rb = INF * 5ll;
 81     while (rb - lb>1) {
 82         mid = (lb + rb) / 2;
 83         if ((LINF / abs(lcm)>abs(mid) && v + mid*lcm >= l) || ((LINF / abs(lcm)<abs(mid)) && !((lcm>0) ^ (mid>0)))) rb = mid;
 84         else lb = mid;
 85     }
 86     ansl = rb;
 87     lb = -INF * 4ll, rb = INF * 4ll;
 88     while (rb - lb>1) {
 89         mid = (lb + rb) / 2;
 90         if (x + mid*a2 / gcd >= 0 && y + mid*a1 / gcd >= 0) rb = mid;
 91         else lb = mid;
 92     }
 93     ansl = max(ansl, rb);
 94     lb = -INF * 4ll, rb = INF * 4ll;
 95     while (rb - lb>1) {
 96         mid = (lb + rb) / 2;
 97         if ((LINF / abs(lcm)>abs(mid) && v + mid*lcm <= r) || (LINF / abs(lcm)<abs(mid) && ((lcm>0) ^ (mid>0)))) lb = mid;
 98         else rb = mid;
 99     }
100     ansr = lb;
101     lb = -INF * 4ll, rb = INF * 4ll;
102     /*while (rb - lb>1) {
103         mid = (lb + rb) / 2;
104         if (x + mid*a2 / gcd >= 0 && y + mid*a1 / gcd >= 0) rb = mid;
105         else rb = mid;
106     }
107     ansr = min(lb, ansr);*/
108     //TO(ansl); TO(ansr);
109     if (ansr<ansl) printf("0
");
110     else printf("%lld
", ansr - ansl + 1);
111 }
112 void get_input() {
113     a1 = read(); b1 = read(); a2 = read(); b2 = read(); l = read(); r = read();
114 }
少女抱B中
E. Generate a String
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

zscoder wants to generate an input file for some programming competition problem.

His input is a string consisting of n letters 'a'. He is too lazy to write a generator so he will manually generate the input in a text editor.

Initially, the text editor is empty. It takes him x seconds to insert or delete a letter 'a' from the text file and y seconds to copy the contents of the entire text file, and duplicate it.

zscoder wants to find the minimum amount of time needed for him to create the input file of exactly n letters 'a'. Help him to determine the amount of time needed to generate the input.

Input

The only line contains three integers nx and y (1 ≤ n ≤ 107, 1 ≤ x, y ≤ 109) — the number of letters 'a' in the input file and the parameters from the problem statement.

Output

Print the only integer t — the minimum amount of time needed to generate the input file.

Examples
input
8 1 1
output
4
input
8 1 10
output
8

 DP方程是显然的,dp[i] = min(dp[i-1]+x,dp[i+1]+x,dp[i/2]+y(if i&1==0)  )

然而这个dp没有一个合理的顺序,不能顺着推,当然可以用最短路的方法做,不过这个n=1e7会t

观察一下,我们发现一个性质:任何时候不会有两个连续的删去字符,证明如下

考虑最开始的两个连续的删去,显然他们不会是最开始的两个操作,我们思考它们前面可能是什么操作

1、输入一个a,那么这显然不优,我们可以讲一次删除和一次输入一起消去

2、复制一次,这显然不优,我们用c代表复制,d代表删除,显然有 cdd = dc,那么dc是更优的选择

有了这个性质,我们可以发现一些有趣的事实:

1、如果i是奇数,它只能是由i+1删去一个字符或者i-1添加一个字符得到(这很显然)

2、如果i是偶数,那么不可能由i+1删去一个字符得到i,因为i+1只能是由i+2删去一个字符或者i添加一个字符得到,如果删去一个字符得到i是不符合我们上面的论断的

那么我们可以有这样的dp方程

i是奇数:dp[i] = min(dp[i-1]+x,dp[(i+1)/2]+x+y)

i是偶数:dp[i] = min(dp[i-1]+x,dp[i/2]+y)

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <string>
 6 #include <cstring>
 7 #include <cmath>
 8 #include <map>
 9 #include <stack>
10 #include <set>
11 #include <vector>
12 #include <queue>
13 #include <time.h>
14 #define eps 1e-7
15 #define INF 0x3f3f3f3f
16 #define MOD 1000000007
17 #define rep0(j,n) for(int j=0;j<n;++j)
18 #define rep1(j,n) for(int j=1;j<=n;++j)
19 #define pb push_back
20 #define set0(n) memset(n,0,sizeof(n))
21 #define ll long long
22 #define ull unsigned long long
23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
24 #define print_runtime printf("Running time:%.3lfs
",double(clock())/1000.0)
25 #define TO(j) printf(#j": %d
",j);
26 //#define OJ
27 using namespace std;
28 const int MAXINT = 10000010;
29 const int MAXNODE = 100010;
30 const int MAXEDGE = 2*MAXNODE;
31 char BUF,*buf;
32 int read(){
33     char c=getchar();int f=1,x=0;
34     while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
35     while(isdigit(c)){x=x*10+c-'0';c=getchar();}
36     return f*x;
37 }
38 char get_ch(){
39     char c=getchar();
40     while(!isalpha(c)) c=getchar();
41     return c;
42 }
43 //------------------- Head Files ----------------------//
44 
45 ll n,x,y,dp[MAXINT];
46 void get_input();
47 void work();
48 int main() {
49     get_input();
50     work();
51     return 0;
52 }
53 void work(){
54     dp[0]=0;
55     for(int i=1;i<=n;i++){
56         if(i&1){
57             dp[i]=min(dp[i-1]+x,dp[(i+1)/2]+x+y);
58         }else{
59             dp[i]=min(dp[i-1]+x,dp[i/2]+y);
60         }
61     }
62     printf("%lld
",dp[n]);
63 }
64 void get_input(){
65     n=read();x=read();y=read();
66 }
少女祈祷中
原文地址:https://www.cnblogs.com/LoveYayoi/p/7009089.html