Educational Codeforces Round 16 D&E.
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.
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).
Print the desired number of integers x.
2 0 3 3 5 21
3
2 4 3 0 6 17
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\n",double(clock())/1000.0) 26 #define TO(j) printf(#j": %lld\n",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\n"); 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\n"); 110 else printf("%lld\n", ansr - ansl + 1); 111 } 112 void get_input() { 113 a1 = read(); b1 = read(); a2 = read(); b2 = read(); l = read(); r = read(); 114 }
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.
The only line contains three integers n, x 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.
Print the only integer t — the minimum amount of time needed to generate the input file.
8 1 1
4
8 1 10
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\n",double(clock())/1000.0) 25 #define TO(j) printf(#j": %d\n",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\n",dp[n]); 63 } 64 void get_input(){ 65 n=read();x=read();y=read(); 66 }