2015-04-10 12:57:22
总结:定期的 asc 训练赛...
第一场打得不是很认真... 中间走神了,以后尽量选在整块的时间来打 asc 。
5h 过了 4题,5h1min过了第 5题,赛后补齐了剩下的3题... 说实话补最后一题(耗时2days)都差点放弃了。。
※本场的一些收获:
(1)完善了高精度模板。
(2)学习了dinic当前弧优化。
(3)学习了上下界流的第二种建图方式。
(4)收获了高斯消元另一个模型。
(5)学习了如何判断点在多边形内。
(6)学习了如何利用dfs树找简单环。
A题:
可以把题目转化为:给出N,找到一个K与N互质且K<=N/2。
试了一些数据发现规律:如果N为奇数,那么答案为(N-1)/2;
如果N为偶数,那么判断N/2的奇偶性,若N/2为偶则答案为N/2-1,若N/2为奇数则答案为N/2-2。
由于题目的数据范围很大... 需要上高精度。
1 #include <cstdio> 2 #include <string> 3 #include <cstring> 4 #include <iostream> 5 using namespace std; 6 const int maxn = 3000; 7 8 struct bign{ 9 int len,s[maxn + 5]; 10 11 //初始化与赋值 12 bign(){ 13 memset(s,0,sizeof(s)); 14 len = 1;//因为0的存在 15 } 16 17 bign operator = (const char *num){ 18 len = strlen(num); 19 for(int i = 0; i < len; ++i) 20 s[i] = num[len - i - 1] - '0';//倒序转化成数字 21 return *this; 22 } 23 24 bign operator = (int num){ 25 char ts[maxn + 5]; 26 sprintf(ts,"%d",num); 27 *this = ts; 28 return *this; 29 } 30 31 bign(int num){ 32 *this = num; 33 } 34 35 bign(const char *num){ 36 *this = num; 37 } 38 //bign的str型转化 39 string str() const{ 40 string res = ""; 41 for(int i = len - 1; i >= 0; --i) 42 res += (char)(s[i] + '0'); 43 if(res == "") 44 res = "0"; 45 return res; 46 } 47 //运算符重载 48 //高精度加 49 bign operator + (const bign & b) const{ 50 bign sum; 51 sum.len = 0; 52 for(int i = 0, g = 0; g || i < max(len,b.len); ++i){ 53 int x = g;//x:暂存和,g:进位 54 if(i < len) x += s[i]; 55 if(i < b.len) x += b.s[i]; 56 sum.s[sum.len++] = x % 10; 57 g = x / 10; 58 } 59 return sum; 60 } 61 62 //高精度减 63 bign operator - (const bign & b) const{ 64 bign dif; 65 int maxlen = (len > b.len) ? len : b.len; 66 for(int i = 0; i < maxlen; ++i){ 67 dif.s[i] += s[i] - b.s[i]; 68 if(dif.s[i] < 0){ 69 dif.s[i] += 10; 70 --dif.s[i + 1]; 71 } 72 } 73 dif.len = maxlen; 74 while(dif.s[dif.len - 1] == 0 && dif.len > 1) 75 --dif.len; 76 return dif; 77 } 78 79 //高精度乘,实际上加和乘对进位的处理有所不同 80 bign operator * (const bign &b) const{ 81 bign pro; 82 pro.len = 0; 83 for(int i = 0; i < len; ++i){ 84 for(int j = 0; j < b.len; ++j){ 85 pro.s[i + j] += (s[i] * b.s[j]); 86 pro.s[i + j + 1] += pro.s[i + j] / 10; 87 pro.s[i + j] %= 10; 88 } 89 } 90 pro.len = len + b.len + 1;//这里注意pro.len初始值可能是题目数字范围两倍 91 while(pro.s[pro.len - 1] == 0 && pro.len > 1) 92 --pro.len;//最后一位不管是不是0都不能让len - 1 93 if(pro.s[pro.len]) 94 ++pro.len;//这句有待商讨 95 return pro; 96 } 97 98 //高精度乘以低精度 99 bign operator * (const int num) const{ 100 int c = 0,t; 101 bign pro; 102 for(int i = 0; i < len; ++i){ 103 t = s[i] * num + c; 104 pro.s[i] = t % 10; 105 c = t / 10; 106 } 107 pro.len = len; 108 while(c != 0){ 109 pro.s[pro.len++] = c % 10; 110 c /= 10; 111 } 112 return pro; 113 } 114 115 //高精度除,模拟连减 116 bign operator / (const bign & b) const{ 117 bign quo,f; 118 for(int i = len - 1; i >= 0; --i){ 119 f = f * 10; 120 f.s[0] = s[i]; 121 while(f >= b){ 122 f = f - b; 123 ++quo.s[i]; 124 } 125 } 126 quo.len = len; 127 while(quo.s[quo.len - 1] == 0 && quo.len > 1) 128 --quo.len; 129 return quo; 130 } 131 132 //比较运算符 133 bool operator < (const bign & b) const{ 134 if(len != b.len) return len < b.len; 135 for(int i = len - 1; i >= 0; --i)//从高位开始比较 136 if(s[i] != b.s[i]) 137 return s[i] < b.s[i]; 138 //如果 本身 == b 139 return false; 140 } 141 142 bool operator > (const bign &b) const{ 143 return b < *this;//代表 本身 > b 144 } 145 146 bool operator <= (const bign &b) const{ 147 return !(b < *this);//带表 !(本身 > b) 148 } 149 150 bool operator >= (const bign &b) const{ 151 return !(*this < b); 152 } 153 154 bool operator != (const bign &b) const{ 155 return *this < b || b < *this; 156 } 157 158 bool operator == (const bign &b) const{ 159 return !(*this < b) && !(b < *this); 160 } 161 162 friend istream & operator >> (istream & in,bign & x); 163 friend ostream & operator << (ostream & out,const bign & x); 164 }; 165 166 istream & operator >> (istream & in,bign & x){ 167 string ts; 168 in >> ts; 169 x = ts.c_str(); 170 return in; 171 } 172 173 ostream & operator << (ostream & out,const bign & x){ 174 out << x.str(); 175 return out; 176 } 177 int main(){ 178 freopen("china.in","r",stdin); 179 freopen("china.out","w",stdout); 180 bign N; 181 bign one = 1,two = 2; 182 cin >> N; 183 bign hf = N / 2; 184 int suf = N.s[0]; 185 if(suf & 1){ 186 cout << hf << endl; 187 } 188 else{ 189 if(hf.s[0] & 1) cout << hf - two << endl; 190 else cout << hf - one << endl; 191 } 192 return 0; 193 }