2019.10.13考试解题报告
总结
期望得分:(100 + 30 + 0)
实际得分:(100 + 50 + 0)
神奇的多得了(20)分?
花两个多小时去推(T1)的式子,结果是推出来了,慌慌张张差点翻车
去打(T2)的暴力,顺便打了几个(if),然后就(30-->50)?心里有点小激动
(T3)没时间做了……我菜
思路
T1
一开始就想写正解,发现不会,于是打了个(40)分的暴力保底,对暴力的式子进行拆解和优化,得到了下面的过程
要求的是
[min sum_{j = 1}^{n} abs(a_i - a_j) * b_j
]
首先去掉绝对值号,发现我们能把这个式子分成两部分
[ ans +=left{
egin{aligned}
sum_{j = 1}^{i}(a_i - a_j) * b_j (a_i > a_j) \
sum_{j = i}^{n}(a_j - a_i) * b_j (a_i < a_j)
end{aligned}
ight.
]
然后拆解发现,前一部分变成了
[a_ib_1 - a_1b_1 + a_ib_2 - a_2b_2 + ……a_ib_j-a_jb_j
]
后一部分变成了
[a_jb_j-a_ib_j+a_{j+1}b_{j+1} -a_ib_{j+1}+……a_nb_n-a_ib_n
]
然后在合并一下子(我懒得写了)
然后发现我们可以用前缀和!!!
然后就做出来了!!
T2
(30)分暴力很好打,暴搜就行了
(60)的话,分别枚举两个骰子点数,计算出来每种点数和的方案数(除以(6^n)得到概率)
如果你扔出了(i)点,那你胜利的方案是对手扔出([1,i)),从小到大枚举你的点数,同时
计算对手的前缀和
满分做法
计算每种点数的概率
计算(i)个骰子的概率时,考虑最后一个骰子的点数为(1-6)的每种情况,可以从(i-1)个骰
子概率转移过来。
记(f[i][j])表示(i)个骰子扔出(j)的概率
(f[i][j] = sum{f[i-1][j-k]/6}(1≤k≤6))
递推即可,复杂度(O(n²))
T3
神仙题神仙题神仙题
代码
T1
考场满分
//By:Loceaner
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
const int N = 1e6 + 11;
struct node {
int a, b, id, c;
} e[N];
bool cmp(node x, node y) {
return x.a < y.a;
}
int n, sum2[N], sum3[N], ans = 0x3f3f3f3f3f3f3f3f;
bool flag = 1;
signed main() {
n = read();
for(int i = 1; i <= n; i++) {
e[i].a = read();
if(i != 1)
if(e[i].a != e[i - 1].a)
flag = 0;
}
for(int i = 1; i <= n; i++) e[i].b = read(), e[i].c = e[i].a * e[i].b;
if(flag) return cout << "0
", 0;
stable_sort(e + 1, e + 1 + n, cmp);
for(int i = 1; i <= n; i++) {
sum2[i] = sum2[i - 1] + e[i].b;
sum3[i] = sum3[i - 1] + e[i].c;
}
// for(int i = 1; i <= n; i++) {
// int now = 0;
// for(int j = 1; j <= n; j++) {
// now += abs(e[i].a - e[j].a) * e[j].b;
// }
// ans = min(ans, now);
// }
int now = 0;
for(int i = 1; i <= n; i++) {
now = e[i].a * sum2[i - 1] - sum3[i - 1] + (sum3[n] - sum3[i]) - e[i].a * (sum2[n] - sum2[i]);
ans = min(ans, now);
}
cout << ans << '
';
return 0;
}
/*
6
2 1 3 3 2 4
5 1 1 2 2 2
10
1 2 2 5 6 6 8 10 10 10
9 55 41 2 4 6 3 2 4 10
*/
题解里的正解
#include<bits/stdc++.h>
#define lson (o<<1)
#define rson (o<<1|1)
#define fi first
#define sc second
#define dbg(x) cout<<#x<<" = "<<(x)<<endl;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
using namespace std;
const double pi=acos(-1);
const double eps=1e-6;
inline int lowbit(int x){return x&(-x);}
inline int read(){
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
template<typename T> inline T max(T x,T y,T z){return max(max(x,y),z);}
template<typename T> inline T min(T x,T y,T z){return min(min(x,y),z);}
template<typename T> inline T sqr(T x){return x*x;}
template<typename T> inline void checkmax(T &x,T y){x=max(x,y);}
template<typename T> inline void checkmin(T &x,T y){x=min(x,y);}
template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}
template<typename A,typename B,typename C> inline A fpow(A x,B p,C yql){
A ans=1;
for(;p;p>>=1,x=1LL*x*x%yql)if(p&1)ans=1LL*x*ans%yql;
return ans;
}
struct FastIO{
static const int S=1310720;
int wpos;char wbuf[S];
FastIO():wpos(0) {}
inline int xchar(){
static char buf[S];
static int len=0,pos=0;
if(pos==len)pos=0,len=fread(buf,1,S,stdin);
if(pos==len)return -1;
return buf[pos++];
}
inline int read(){
int c=xchar(),x=0;
while(c<=32&&~c)c=xchar();
if(c==-1)return -1;
for(;'0'<=c&&c<='9';c=xchar())x=x*10+c-'0';
return x;
}
}io;
//#define read io.read
const int N=1e6+10;
const int yql=1e9+7;
struct Node{
int x,v;
}a[N];
inline bool cmp(Node a,Node b){return a.x<b.x;}
int n,m;
ll cur=0,ans=0,k1,k2;
int main(){
freopen("shiroha1.in","r",stdin);
freopen("shiroha1.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)a[i].x=read();
for(int i=1;i<=n;i++)a[i].v=read();
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)cur=cur+1LL*(a[i].x-a[1].x)*a[i].v;
ans=cur;
for(int i=2;i<=n;i++)k1+=a[i].v;k2=a[1].v;
for(int i=2;i<=n;i++){
//dbg(cur);
//cur=(cur-1LL*k1*(a[i].x-a[i-1].x)%yql+yql)%yql;
//cur=(cur+1LL*k2*(a[i].x-a[i-1].x)%yql)%yql;
cur=cur-1LL*k1*(a[i].x-a[i-1].x);
cur=cur+1LL*k2*(a[i].x-a[i-1].x);
k1-=a[i].v;k2+=a[i].v;
checkmin(ans,cur);
}
printf("%lld
",ans);
}
T2
暴力
//By:Loceaner
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
int x, y, nowx, nowy, cnta, cntb, cntp;
void dfs2(int tot, int ans) {
if(tot == y) {
nowy = ans;
if(nowx == nowy) cntp++;
else if(nowx > nowy) cnta++;
else cntb++;
return;
}
for(int i = 1; i <= 6; i++) {
dfs2(tot + 1, ans + i);
}
}
void dfs1(int tot, int ans) {
if(tot == x) {
nowx = ans;
dfs2(0, 0);
return;
}
for(int i = 1; i <= 6; i++) {
dfs1(tot + 1, ans + i);
}
}
int main() {
x = read(), y = read();
if(x + y <= 10) {
dfs1(0, 0);
printf("%.2lf%%", ((1.0 * cnta) / (cnta + cntb + cntp)) * 100);
}
else if(x - 7 >= y) cout << "100.00%";
else if(y - 7 >= x) cout << "0.00%";
else if(x > y * 6) cout << "100.00%";
else if(x == y) cout << "50%";
else cout << "0.00%";
return 0;
}
正解
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
double a[1001][7001], sx, sy, ans;
int x, y;
int main() {
scanf("%d%d", &x, &y);
int xy = x > y ? x : y;
for(int i = 1; i <= 6; i++) a[1][i] = 1;
for(int i = 2; i <= xy; i++)
for(int j = i; j <= 6 * i; j++)
for(int k = 1; k <= 6; k++)
if(j > k) a[i][j] += a[i - 1][j - k] / 6.0;
for(int i = x; i <= 6 * x; i++) {
for(int j = y; j <= 6 * y; j++)
sy += a[x][i] * a[y][j];
if(i <= y) continue;
for(int j = y; j <= i - 1; j++)
sx += a[y][j] * a[x][i];
}
ans = sx / sy * 100;
printf("%.2lf%%", ans);
return 0;
}
T3
正解
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1000010;
const int MAXL = 22;
int rmin[MAXL][MAXN], rmax[MAXL][MAXN];
int n, q;
int a[MAXN];
inline void init_rmq() {
for (int i = 1; i < MAXL; i++) {
for (int j = 0; j + (1 << i) <= n; j++) {
rmin[i][j] = min(rmin[i-1][j], rmin[i-1][j+(1<<(i-1))]);
rmax[i][j] = max(rmax[i-1][j], rmax[i-1][j+(1<<(i-1))]);
}
}
}
inline bool test(int d, int m) {
int l = 0, i;
for (i = 0; i < m && l < n; i++) {
int r = l, smin = 1000000001, smax=0;
for (int j = MAXL - 1; j >= 0; j--) {
if (r + (1 << j) <= n) {
int tmin = rmin[j][r], tmax = rmax[j][r];
if (max(smax, tmax) - min(smin, tmin) <= d) {
smax = max(smax, tmax);
smin = min(smin, tmin);
r += (1 << j);
}
}
}
l = r;
}
return l == n;
}
inline int work(int m) {
int l = 0, r = 1000000001;
while (l < r) {
int mid = (l + r) >> 1;
if (test(mid, m)) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%*d%d", &rmin[0][i]);
rmax[0][i] = rmin[0][i];
}
init_rmq();
scanf("%d", &q);
for (int i = 0; i < q; i++) {
int m;
scanf("%d", &m);
int ans = work(m);
if (ans % 2) printf("%d.5
", ans/2);
else printf("%d
", ans/2);
}
}