
句柄:N个等差数列,初项X_i,末项Y_i,公差Z_i,求出现奇数次的数?
3.1不光是查找值!“二分搜索”
其他
这题的难点在于……IO,数据集之间可能有多个空行,而且也没指定数据的上限,全靠瞎猜,欧洲人都这么散漫?
假设所有数的出现次数分别为C_1、C_2……C_n,题目中还规定次数为奇数的只有一个,那么假定C_x为奇数,其他都为偶数。设数列T为{T_i, T_i = C_1 + … + C_i},如果i>=x则T_i一定为奇数,否则一定为偶数。这就是二分的单调性,通过判断此奇偶性就可以推断x与i的位置关系。
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#define MAX_CASE 1000000
typedef unsigned long long ULL;
ULL X[MAX_CASE], Y[MAX_CASE], Z[MAX_CASE];
ULL C[MAX_CASE]; // 每个数列中有几个数
int N;
ULL count_sum(const ULL& limit)
{
ULL sum = 0;
for (int i = 0; i < N; ++i)
{
if (limit >= Y[i])
{
sum += C[i];
}
else if (limit >= X[i])
{
sum += (limit - X[i]) / Z[i] + 1;
}
}
return sum;
}
char buf[1024];
bool input()
{
int f = 0;
N = 0;
while ((f = ((gets(buf) != NULL))) && strlen(buf) > 2)
{
sscanf(buf, "%I64d %I64d %I64d", &X[N], &Y[N], &Z[N]);
N++;
}
return f || N;
}
///////////////////////////SubMain//////////////////////////////////
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
string line;
while (input())
{
if (!N)
{
continue;
}
ULL last_bit = 0; // 判断奇数的个数的奇偶性,只有最后一位有用
for (int i = 0; i < N; ++i)
{
C[i] = (Y[i] - X[i]) / Z[i] + 1; // 初项减末项除公差
last_bit ^= C[i]; // 奇数的最后一位是1,两个奇数异或之后变为0,一奇一偶还是1
}
if (!(last_bit & 1))
{
cout << "no corruption" << endl;
}
else
{
ULL lb = 0, ub = 0xffffffff;
while (ub - lb > 0)
{
ULL mid = (ub + lb) >> 1;
if (count_sum(mid) & 1)
{
// 还在前面
ub = mid;
}
else
{
lb = mid + 1;
}
}
cout << lb << ' ' << count_sum(lb) - count_sum(lb - 1) << endl;
}
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
///////////////////////////End Sub//////////////////////////////////
唉,本来想用我优雅的stream的,但是就是TLE,留个纪念:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#define MAX_CASE 1000000
typedef unsigned long long ULL;
ULL X[MAX_CASE], Y[MAX_CASE], Z[MAX_CASE];
ULL C[MAX_CASE]; // 每个数列中有几个数
int N;
ULL count_sum(const ULL& limit)
{
ULL sum = 0;
for (int i = 0; i < N; ++i)
{
if (limit >= Y[i])
{
sum += C[i];
}
else if (limit >= X[i])
{
sum += (limit - X[i]) / Z[i] + 1;
}
}
return sum;
}
///////////////////////////SubMain//////////////////////////////////
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
string line;
while (getline(cin, line) || N)
{
if (line.length())
{
stringstream sstream;
sstream << line;
sstream >> X[N] >> Y[N] >> Z[N];
++N;
line.clear();
}
else
{
if (!N)
{
continue;
}
ULL last_bit = 0; // 判断奇数的个数的奇偶性,只有最后一位有用
for (int i = 0; i < N; ++i)
{
C[i] = (Y[i] - X[i]) / Z[i] + 1; // 初项减末项除公差
last_bit ^= C[i]; // 奇数的最后一位是1,两个奇数异或之后变为0,一奇一偶还是1
}
if (!(last_bit & 1))
{
cout << "no corruption" << endl;
}
else
{
ULL lb = 0, ub = 0xffffffff;
while (ub - lb > 0)
{
ULL mid = (ub + lb) >> 1;
if (count_sum(mid) & 1)
{
// 还在前面
ub = mid;
}
else
{
lb = mid + 1;
}
}
cout << lb << ' ' << count_sum(lb) - count_sum(lb - 1) << endl;
}
N = 0;
}
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
///////////////////////////End Sub//////////////////////////////////
| 12852969 | hankcs | 3484 | Accepted | 832K | 94MS | C++ | 1741B | 2014-05-08 18:29:34 |
知识共享署名-非商业性使用-相同方式共享:码农场 » POJ 3484 Showstopper 题解 《挑战程序设计竞赛》
码农场