以下是让人头疼的购物单,为了保护隐私,物品名称被隐藏了。
**** 180.90 88折
**** 10.25 65折
**** 56.14 9折
**** 104.65 9折
**** 100.30 88折
**** 297.15 半价
**** 26.75 65折
**** 130.62 半价
**** 240.28 58折
**** 270.62 8折
**** 115.87 88折
**** 247.34 95折
**** 73.21 9折
**** 101.00 半价
**** 79.54 半价
**** 278.44 7折
**** 199.26 半价
**** 12.97 9折
**** 166.30 78折
**** 125.50 58折
**** 84.98 9折
**** 113.35 68折
**** 166.57 半价
**** 42.56 9折
**** 81.90 95折
**** 131.78 8折
**** 255.89 78折
**** 109.17 9折
**** 146.69 68折
**** 139.33 65折
**** 141.16 78折
**** 154.74 8折
**** 59.42 8折
**** 85.44 68折
**** 293.70 88折
**** 261.79 65折
**** 11.30 88折
**** 268.27 58折
**** 128.29 88折
**** 251.03 8折
**** 208.39 75折
**** 128.88 75折
**** 62.06 9折
**** 225.87 75折
**** 12.89 75折
**** 34.28 75折
**** 62.16 58折
**** 129.12 半价
**** 218.37 半价
**** 289.69 8折
180.90 88
10.25 65
56.14 90
104.65 90
100.30 88
297.15 50
26.75 65
130.62 50
240.28 58
270.62 80
115.87 88
247.34 95
73.21 90
101.00 50
79.54 50
278.44 70
199.26 50
12.97 90
166.30 78
125.50 58
84.98 90
113.35 68
166.57 50
42.56 90
81.90 95
131.78 80
255.89 78
109.17 90
146.69 68
139.33 65
141.16 78
154.74 80
59.42 80
85.44 68
293.70 88
261.79 65
11.30 88
268.27 58
128.29 88
251.03 80
208.39 75
128.88 75
62.06 90
225.87 75
12.89 75
34.28 75
62.16 58
129.12 50
218.37 50
289.69 80
再写以下代码计算出答案。
#include
using namespace std;
int main() {
double x, y, res = 0;
for(int i = 1; i <= 50; ++i) {
cin >> x >> y;
res += x * (y / 100);
}
cout << res;
return 0;
}
答案:5200(5136.86)
题意:
做法:其实搜索的时候并没有满怀信心 ,就是暴力就好了,还比较害怕数组没开够,没能找到公差更小的,其实在5000以内就够了,这谁想的到 。
代码:
#include
using namespace std;
const int N = 1e6+10;
int prime[N], vis[N], k;
int check(int d) {
int res = 210;
for(int i = 0; i < k-10; ++i) {
int f = 1, lst = prime[i];
if(d == res) cout << lst << " ";
for(int j = 0; j < 9; ++j) {
if(d==res)cout << lst + d << " ";
if(lst+d>=N) {
f = 0; break;
}
if(vis[lst+d]) {
f = 0; break;
}
lst = lst + d;
}
if(d==res) cout << endl;
if(f) return 1;
}
return 0;
}
int main() {
vis[0] = vis[1] = 1;
for(int i = 2; i < N; ++i) {
if(!vis[i]) {
prime[k++] = i;
for(int j = 2*i; j < N; j += i) vis[j] = 1;
}
}
//for(int i = 0; i < k; ++i) printf("%d\n", prime[i]);
for(int i = 2; i <= 1000; ++i) {
if(check(i)) {
cout << i; break;
}
}
return 0;
}
答案:210
代码:
#include
using namespace std;
const int N = 100;
double tu[N][N];
int main() {
double sum = 0;
for(int i = 1, x; i < 30; ++i) {
for(int j = 1; j <= i; ++j) {
cin >> x;
tu[i][j] += x; sum += x;
tu[i+1][j] += tu[i][j]/2; tu[i+1][j+1] += tu[i][j]/2;
}
}
double res = 0, check = 10000000000.0, sumcheck = 0;
for(int j = 1; j <= 30; ++j) {
sumcheck += tu[30][j];
res = max(res, tu[30][j]);
check = min(check, tu[30][j]);
}
cout << endl;
cout << sum << " " << sumcheck << endl;
cout << res << " " << check << endl;
printf("%.3lf\n", 2086458231.0 / check * res);
return 0;
}
答案:72665192664
做法:可以发现一个对称的图形肯定关于中间的点对称,那么从中间的点开始搜索所到之处关于中间点对称的点也标记为1,每次走到边界就是一个新的图啦,将结果加一。
代码:
#include
using namespace std;
const int N = 10;
const int ne[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
int vis[N][N];
int ans;
void dfs(int x, int y) {
if(x <= 0 || y <= 0 || x >= 6 || y >= 6) {
++ans; return;
}
for(int i = 0, tx, ty; i < 4; ++i) {
tx = x + ne[i][0]; ty = y + ne[i][1];
if(!vis[tx][ty] && !vis[6-tx][6-ty]) {
vis[tx][ty] = vis[6-tx][6-ty] = 1;
dfs(tx, ty);
vis[tx][ty] = vis[6-tx][6-ty] = 0;
}
}
}
int main() {
vis[3][3] = 1;
dfs(3, 3);
cout << ans/4;
return 0;
}
答案:509
题意:
做法:类似动态规划,上一个状态从a[i-1][j-1]转移而来。
答案:a[i-1][j-1]+1
题意:
做法:题意很简单,但是坑很多,首先要注意闰年的情况,还有千万要去重,因为没去重找了半天的bug。
代码:
#include
using namespace std;
const int N = 10;
struct xx {
int y, m, d;
bool operator < (const xx &c) const {
if(y != c.y) return y < c.y;
if(m != c.m) return m < c.m;
return d < c.d;
}
}res[N];
int k;
int month[14] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int isr(int y) {
if(y % 4 == 0 && y % 100 != 0 || y % 400 == 0) return 1;
return 0;
}
void solve(int a, int m, int d) {
if(m <= 0 || m > 12 || d <= 0 || d > 31) return;
int q = 1900, n = 2000;
int y = q + a;
if(y >= 1960) {
month[2] = isr(y) ? 29 : 28;
if(d <= month[m]) {
res[k].y = y; res[k].m = m; res[k++].d = d;
}
}
y = n + a;
if(y <= 2059) {
month[2] = isr(y) ? 29 : 28;
if(d <= month[m]) {
res[k].y = y; res[k].m = m; res[k++].d = d;
}
}
return ;
}
int main() {
int a, b, c;
scanf("%d/%d/%d", &a, &b, &c);
solve(a, b, c); solve(c, a, b); solve(c, b, a);
sort(res, res+k);
printf("%d-%02d-%02d\n", res[0].y, res[0].m, res[0].d);
for(int i = 1; i < k; ++i) {
if(res[i].y == res[i-1].y && res[i].m == res[i-1].m && res[i].d == res[i-1].d)
continue;//去重!!!
printf("%d-%02d-%02d\n", res[i].y, res[i].m, res[i].d);
}
return 0;
}
题意:
做法:首先要知道无法凑到无限个数字的情况是这n个数字的最大公约数不是1,然后还需要知道的是,若最大公约数是1,那么一个数字大到一定程度(10000左右),一定能由这几个数字组成,知道这两个结论后,就可以递推暴力出ac了。
代码:
#include
using namespace std;
const int N = 110;
const int M = 100010;
int a[N], dp[M];
int main() {
int n; scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
if(n == 1) {
if(a[1] == 1) puts("0");
else puts("INF");
return 0;
}
int f = __gcd(a[1], a[2]);
for(int i = 3; i <= n; ++i) {
f = __gcd(f, a[i]);
}
if(f != 1) {
puts("INF"); return 0;
}
dp[0] = 1;
for(int i = 1; i <= n; ++i) {
for(int j = 0; j + a[i] < M; ++j) {
if(dp[j]) dp[j+a[i]] = 1;
}
}
int res = 0;
for(int i = 1; i < M; ++i) {
if(!dp[i]) ++res;
}
cout << res << endl;
return 0;
}
题意:
做法:二分答案,二分的时候要注意细节,二分分很多种,有靠近左边界的二分,靠近右边界的二分,这题是靠近右边界的二分,所以最后答案-1了,具体二分细节学习戳这,每次判断这个答案是否正确,用的是这个思想。
代码:
#include
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define PI acos(-1)
#define eps 1e-8
#define rint register int
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<double, int> pdi;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<int, int> mii;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int ne[8][2] = {1, 0, -1, 0, 0, 1, 0, -1, -1, -1, -1, 1, 1, -1, 1, 1};
const int INF = 0x3f3f3f3f;
const int N = 1e5+10;
const LL Mod = 1e9+7;
const int M = 1e6+10;
int h[N], w[N];
int n, k;
int check(int x) {
LL sum = 0;
//cout << x << ": ";
for(int i = 0, m; i < n; ++i) {
m = (h[i]/x)*(w[i]/x);
sum += m;
}
//cout << sum << endl;
return sum >= k;
}
int main() {
scanf("%d %d", &n, &k);
for(int i = 0; i < n; ++i) scanf("%d %d", &h[i], &w[i]);
int l = 1, r = N, mid;
while(l < r) {
mid = l + r >> 1;
if(check(mid)) l = mid + 1;
else r = mid;
}
printf("%d\n", l-1);
return 0;
}
做法:是一个前缀和思维问题,我真的觉得最后一题比前面的题目要简单 。可以有一个简单的猜想,这个区间问题可以轻易的转化成,前缀和中两个数的差值是k的倍数,那么也就是说要满足(sum[j]-sum[i])%k==0,也就是说sum[j]%k == sum[i]%k,也就是说,如果前缀和中两个数字取膜k等于相同的数字,那么这两个数字相减就必是k的倍数,这两个数字构成的区间就是k倍区间。
首先看样例
数组为 0 1 2 3 4 5
前缀和为 0 1 3 6 10 15
前缀和膜k为 0 1 1 0 0 1
能构成的区间就有 C 3 2 + C 3 2 = 6 C_3^2 + C_3^2 = 6 C32+C32=6个,分别是(0,3],(0,4],(1,2],(1,5],(2,5],(3,4]
代码:
#include
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define PI acos(-1)
#define eps 1e-8
#define rint register int
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<double, int> pdi;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<int, int> mii;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int ne[8][2] = {1, 0, -1, 0, 0, 1, 0, -1, -1, -1, -1, 1, 1, -1, 1, 1};
const int INF = 0x3f3f3f3f;
const int N = 1e5+10;
const LL Mod = 1e9+7;
const int M = 1e6+10;
LL sum[N], a[N], cnt[N];
int main() {
int n, k;
scanf("%d %d", &n, &k);
_rep(1, n, i) {
scanf("%lld", &a[i]);
sum[i] = (sum[i-1] + a[i]) % k;
++cnt[sum[i]];
}
++cnt[0];
LL res = 0;
//cout << cnt[0] << " " << cnt[1] << endl;
_for(0, k, i) {
if(cnt[i] > 1) res += cnt[i] * (cnt[i]-1) / 2;
}
printf("%lld\n", res);
return 0;
}