A. Jeff and Digits
链接:http://codeforces.com/contest/352/problem/A
描述:给定n个数,每个数字是0或者5,(1<=n<=1000).求一个最大的能被90整除的数。
思路:直接找规律,当5的个数是9的倍数时能被90整除。注意0的个数处理。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
int a[n];
for (int i = 0; i < n; ++i)
scanf("%d", &a[i]);
int num5 = 0, num0 = 0;
for (int i = 0; i < n; ++i)
{
if (a[i] == 5)
++num5;
if (a[i] == 0)
++num0;
}
if (num0 == 0)
{
printf("-1\n");
return 0;
}
if (num5 < 9 && num0 > 0)
{
printf("0\n");
return 0;
}
int t = num5 / 9;
for (int i = 0; i < t * 9; ++i)
printf("5");
for (int i = 0; i < num0; ++i)
printf("0");
printf("\n");
return 0;
}
B. Jeff and Periods
链接:http://codeforces.com/contest/352/problem/B
描述:给定n(1<=n<=10^5)个数的数组,a1,a2.......an (1<=ai<=10^5).求满足这两个条件的所有x:
1.x出现在a数组中。
2.对于所有出现x的位置下表i,这些下标组成等差数列。
思路:我的思路就是用map< int , vector<int> >,把每个数组元素的下标按照升序添加到它所对应的vector中,然后判断vector中的下标是不是等差数列。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
const int M = 100000 + 10;
using namespace std;
int main()
{
int n;
scanf("%d", &n);
map< int, vector<int> > t;
int val;
for (int i = 1; i <= n; ++i)
{
cin >> val;
t[val].push_back(i);
}
map< int, vector<int> >::iterator it;
int sum = 0; //sum 存储符合条件的x的个数
int res1[M], res2[M]; //res1,res2对应每个x和公差
for (it = t.begin(); it != t.end(); ++it)
{
if ((it->second).size() == 1)
{
res1[sum] = it->first;
res2[sum] = 0;
sum++;
continue;
}
bool ok = 1;
int dif = (it->second)[1] - (it->second)[0];
for (int i = 2; i < (it->second).size(); ++i)
{
if ((it->second)[i] - (it->second)[i-1] != dif)
{
ok = 0;
break;
}
}
if (ok)
{
res1[sum] = it->first;
res2[sum] = dif;
sum++;
}
}
cout << sum << endl;
for (int i = 0; i < sum; ++i)
{
cout << res1[i] << " " << res2[i] << endl;
}
return 0;
}
C. Jeff and Rounding(Codeforces Round #204 (Div. 1)A. Jeff and Rounding)
链接:http://codeforces.com/problemset/problem/351/A
描述:首先输入n(1<=n<=2000), 然后是2*n个浮点数,选n对浮点数,每一对浮点数其中一个数下取整,另一个数上取整,然后求2*n个处理后浮点数的和与处理前浮点数的和的差的绝对值的最小值。
即min |(a1+a2+.....+an)-([ai1+aj1]+[ai2+aj2]+.....+[ain+ajn])|
思路:我的思路是这样的,不知道对不对。
先看几个简单的整数函数公式:定义ceil表示上取整,floor表示下取整,fmod表示取小数部分
ceil(x) = floor(x) 当且仅当x为整数
ceil(x) = floor(x) + 1 当且仅当x不是整数
本题每次选取有三种情况:(整数是指a.000的格式)
1.两个整数:前后绝对值之差为0。
2.一个整数一个小数:小数可以是上取整或者下取整,假设ai是整数,ceil(ai) = floor(ai)
min( |ai+aj-floor(ai)-ceil(aj)|, |ai+aj-ceil(ai)-floor(aj)| )
//用上面的两个公式转化
=min( |ai-floor(ai)+aj-floor(aj)-1|, |ai-floor(ai)+aj-floor(aj)| )
=min( |fmod(ai)+fmod(aj)-1|, |fmod(ai)+fmod(aj)| )
=min( |fmod(aj)-1|,abs( fmod(aj)) )
3.两个小数:
min( |ai+aj-floor(ai)-ceil(aj)|, |ai+aj-ceil(ai)-floor(aj)| )
=min( |ai-floor(ai)+aj-floor(aj)-1|, |ai-floor(ai)-1+aj-floor(aj)| )
=|fmod(ai)+fmod(aj)-1|
可以看出,第一种和第三种答案已经固定了,只有第二种需要考虑,即找到zeronum(zeronum<=n)个整数和小数配对,取一个最小值。 而第二种情况的结果就是aj的小数部分要不要减去1的问题。
为了避免精度问题,可以都当作整数读取。
#include <iostream>
#include <functional>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int INF = 0x7fffffff;
int main()
{
int n;
scanf("%d", &n);
int intpart, facpart, sum = 0, zeronum = 0;
for (int i = 0; i < n * 2; ++i)
{
scanf("%d.%d", &intpart, &facpart);
sum += facpart;
if (facpart != 0)
++zeronum;
}
int L = max(0, zeronum - n);
int R = min(zeronum, n);
int ans = INF;
for (int i = L; i <= R; ++i)
ans = min(ans, abs(sum - i*1000));
printf("%d.%03d\n", ans / 1000, ans % 1000);
return 0;
}