题目描述:给出若干组数据,每组数据包括若干个数列,数列给出首项x[i],末项y[i],公差z[i],问对于每组数据的所有数列中,出现奇数次的数字是多少,以及出现了多少次。
题解:
此题堪称继数论以后,第一坑的题目。
首先读入把人难倒了——先用gets读一行,再判断字符串的长度,若为0则表示一组新数据的开始,不为0则用sscanf转化成int类型,对于初学C++的新手。。泪奔。。。
二分结果,定义Sum[mid,i]=C[1]+C[2]+...C[i](i表示是该组数据中的第i个数列,C表示该个数列中小于mid的个数),可以肯定的说,如果mid出现的是奇数次,则Sum也是奇数(因为题目指明只有一个奇数),则范围可以继续缩小,否则将范围扩大。
再者,此题,用stringsteam似乎比较方便(又是一深奥东东,再次泪。。),但会超时,也就是说,比赛时,除了C++的STL库,其他C++的特性都比较慢。。。。
参考程序:
#include<cstdio>
#include<algorithm>
#include<string>
#define INF 0x7f7f7f7f
#define maxn 2100000
using namespace std;
int cnt;
char str[1024];
long long x[maxn],y[maxn],z[maxn];
long long c[maxn];
long long Count(long long limit){
long long sum=0;
for (int i=0;i<cnt;i++){
if (limit>=y[i])sum+=c[i];
else if (limit>=x[i])sum+=(limit-x[i])/z[i]+1;
}
return sum;
}
void solve(){
long long Bit;
for (int i=0;i<cnt;i++){
c[i]=(y[i]-x[i])/z[i]+1;
Bit^=c[i];
}
if (!(Bit & 1)){
printf("no corruption\n");
return;
}
long long l=0,r=INF;
while(l<r){
long long mid=(l+r)>>1;
if (Count(mid)&1)r=mid;
else l=mid+1;
}
printf("%lld %lld\n",l,Count(l)-Count(l-1));
}
int main(){
cnt=0;
while (gets(str)!= NULL){
if (strlen(str)==0){
if (!cnt)continue;
solve();
cnt=0;
}else{
sscanf(str,"%lld %lld %lld",&x[cnt],&y[cnt],&z[cnt]);
cnt++;
}
}
if (cnt)solve();
return 0;
}