题意:告诉n组A,B,C,按照A + k * C生成等差数列,问这n组数列中哪个数字出现了奇数次以及出现了几次,题目保证最多只会出现一个这种数字。
分析:读完题并没有思路,后来知道是二分区间,枚举是哪个数字出现了奇数次,算该数字之前一共有几个数字,如果是奇数个,说明答案就在[L , Mid]中。
PS:之前用二分只是枚举具体要求的数字,原来枚举区间也可以。二分的时候 l = mid + 1,r = mid ;(一开始r = mid + 1,l = mid就无限循环,手算并没有错啊?很奇怪。。。)
1 #include <cstdio> 2 #include <iostream> 3 #include <sstream> 4 #include <cmath> 5 #include <cstring> 6 #include <cstdlib> 7 #include <string> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <stack> 13 #include <algorithm> 14 using namespace std; 15 #define ll long long 16 #define _cle(m, a) memset(m, a, sizeof(m)) 17 #define repu(i, a, b) for(int i = a; i < b; i++) 18 #define repd(i, a, b) for(ll i = b; i >= a; i--) 19 #define sfi(n) scanf("%d", &n) 20 #define pfi(n) prllf("%d\n", n) 21 #define INF 0x3f3f3f3f3f 22 #define N 20010 23 ll a[N],b[N],c[N]; 24 int n; 25 ll judge(ll p)///p之前已经发了多少张传单了 26 { 27 ll sum = 0; 28 repu(i,0,n) 29 { 30 ll t = min(p,b[i]); 31 if(t >= a[i]) 32 sum += ((t - a[i])/c[i] + 1ll); 33 } 34 return sum%2ll; 35 } 36 int main() 37 { 38 while(~scanf("%d",&n)) 39 { 40 ll sum = 0ll,t = 0ll,l = INF,r = 0ll; 41 repu(i,0,n) 42 { 43 scanf("%I64d%I64d%I64d",&a[i],&b[i],&c[i]); 44 r = max(r,b[i]); 45 l = min(l,a[i]); 46 } 47 if(!judge(r)) 48 { 49 printf("DC Qiang is unhappy.\n"); 50 continue; 51 } 52 ll mid = 0ll; 53 while(l < r) 54 { 55 mid = (l + r)/2ll; 56 if(judge(mid))///如果是奇数 57 r = mid ; 58 else 59 l = mid +1ll; 60 } 61 ///求具体有几张 62 sum = 0ll; 63 repu(i,0,n) 64 { 65 if(r >= a[i] && r <= b[i]) 66 if((r - a[i])%c[i] == 0) 67 sum++; 68 } 69 printf("%I64d %I64d\n",r,sum); 70 } 71 return 0; 72 }
时间: 2024-10-13 12:23:31