标签:-- 鄙视 选择 pop 浮点数 位置 can 没有 empty
题1:非负的部分和 【题目描述】 WZK最近收到了一个任务。 给出一个 n 个数的序列,为 A0,A1,,,,An-1,循环移动 k 位之后,这 成了 Ak,Ak+1,,,,An-1,A0,A1,,,,Ak-1。一种优秀的循环移动是, 前i(1<=i<=n)项和都满足不小于零。请给出这个序列优秀循环移动的个数。 这道题目当然是很简单啦,但是 WZK忙着吃小浣熊干脆面,手上油油的写不 是就麻烦你啦!如果能做到满分,他就会考虑请你吃一包哦~ 【输入格式】 第一行一个整数 n(1 <= n <= 10^6),表示有n个数。 第二行n个整数,Ai(-1000 <= Ai <= 1000)表示给出的第i 个数。 【输出格式】 一行一个整数,表示优秀循环移动的个数。 【样例输入】 3 2 2 1 【样例输出】
很神奇的题,直接单调队列维护就好了
手推很容易出公式的,qwq
#include<bits/stdc++.h> #define I inline using namespace std; const int N=1e6+7; int a[N],s[N*2],n,ans; deque<int> que; I int read() { int x=0,f=1;char ch=getchar(); while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); n=read(); for (int i=1;i<=n;i++) s[i]=s[i-1]+read(),s[i+n]=s[i]; for (int i=n+1;i<=2*n;i++) s[i]+=s[n]; que.push_back(1); for (int i=1;i<n;i++) { while (!que.empty()&&s[que.back()]>s[i]) que.pop_back(); que.push_back(i); } for (int i=n;i<2*n;i++) { if (que.front()<=i-n) que.pop_front(); while (!que.empty()&&s[que.back()]>s[i]) que.pop_back(); que.push_back(i); if (s[que.front()]-s[i-n]>=0) ans++; } printf("%d\n",ans); return 0; }
第二道题我到现在都没有想出来正解
所以就咕咕咕了,有大佬想吊打我的,请随手切了教教我呗
题面如下:
【题目描述】 WZK在众人的鄙视之下,终于下定决心要减肥了。他发现网球选手的身材都很好,于是 找来好友YJC来进行网球比赛。 下面还是简单的讲述一下网球比赛的计分规则: 局:一局比赛只有一名选手发球,率先赢得至少 4分并多出对手至少2分的选手赢得一 局。网球每局的记分方法十分特殊,从 0 至 3 分分别为“零”(love)、“十五”(fifteen)、 “三十”(thirty)和“四十”(forty)。记分时,发球手的得分在前。因此“30 比0”的意 思是,发球手赢得 2 分,而接球手还未得分。当双方选手都得到了 3 分时,一般叫“平局” (deuce)而非“40比 40”。在出现平局后一名球手再得一分,被称为“占先”(advantage), 而不再记分。如果在占先的情况下失去一分,就再度回到平局;如占先后再得一分,就赢得一局。 盘:当一名选手至少赢得4局并且至少比对手领先两局时,就赢得了这一盘。当双方赢 得的局数为6-6时,则进入“抢七”。 抢七:抢七局中,记分采用正常的数列表示,率先获得 7分并领先对手至少2 分的选手 获胜。 比赛:赢得两盘的选手即赢得了比赛。 虽然他们感情很好,WZK还是想要赢得比赛。WZK潜心研究了自己赢得1 分的概率,WZK 想知道他赢得1局、1 盘和整个比赛的概率是多少。(要是太低咱就不比了是吧) 【输入格式】 多组测试数据。 每一组测试数据,输入一行 1个实数 p(0 <= p <= 1),表示WZK赢得1分的概率。 【输出格式】 对于每一组数据,输出一行 3 个 11 位小数,分别表示 WZK 赢得 1 局、1 盘和整个比赛 的概率。 【样例输入】 0.5 0.3 0.7 【样例输出】 0.50000000000 0.50000000000 0.50000000000 0.09921103448 0.00016770463 0.00000008437 0.90078896552 0.99983229537 0.99999991563
第三道题,我最初想的是这排列出来之后没法搞啊,有50!的排列数
结果,之后我很神奇的发现,我们其实有个最优策略:
我们定当前方向为180度的方向,直接将forward用完,之后再在剩下的所有可转角度中,选择一个距离360度最近的角度
再把backward用完,之后剩下的操作一次转完就够了呀qwq,最后ans即余弦定理算出即可
题3:WZK 的豪华游轮 【题目描述】 WZK 经过一辈子的奋斗,终于攒够钱买了一条豪华游轮(其实就是条小木船),这种船 可以执行4种指令: right X : 其中 X是一个1到719的整数,这个命令使得船顺时针转动X 度。 left X : 其中X 是一个1到719的整数,这个命令使得船逆时针转动X度。 forward X : 其中 X是一个整数(1到 1000),使得船向正前方前进X 的距离。 backward X : 其中X是一个整数(1到 1000),使得船向正后方前进X 的距离。 WZK随意的写出了 n个命令,他想找出一个种排列命令的方法,使得船最终到达的位置 距离起点尽可能的远。 【输入格式】 第一行一个整数 n(1 <= n <= 50),WZK给出的命令数。 接下来n行,每行表示一个命令。 【输出格式】 一个浮点数,能够走的最远的距离,四舍五入到 6位小数。 【样例输入】 3 forward 100 backward 100 left 90 【样例输出】 141.421356
上面是题面,下面奉上我丑陋的代码:
#include<bits/stdc++.h> #define db double using namespace std; const int N=101; const double PI=acos(-1.0); bool dp[51][N<<4]; int fro,bac,lf,rg; struct node { int d,opt; } t[N]; int cnt,n; double sqr(double x) { return x*x; } int main() { freopen("ship.in","r",stdin); freopen("ship.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) { char s[N];scanf("%s",s); int x;scanf("%d",&x); if (s[0]==‘f‘) fro+=x; if (s[0]==‘b‘) bac+=x; if (s[0]==‘l‘) t[++cnt].d=x,t[cnt].opt=0; if (s[0]==‘r‘) t[++cnt].d=x,t[cnt].opt=1; } dp[0][180]=true; for (int i=1;i<=cnt;i++) { for (int j=0;j<360;j++) { if (dp[i-1][j]) { dp[i][j]=dp[i-1][j]; if (t[i].opt) dp[i][(j-t[i].d+720)%360]=true; else dp[i][(j+t[i].d)%360]=true; } } } int a=0,b=0,p; for (int i=0;i<=180;i++) if (dp[cnt][i]) {a=i;break;} for (int i=359;i>=180;i--) if (dp[cnt][i]) {b=i;break;} p=min(a,360-b);p=180-p; double fp=cos(p/180.0*PI); double ans=sqrt(sqr((db)fro)+sqr((db)bac)-2*fro*bac*fp); printf("%.6lf\n",ans); return 0; }
中间要做一次01 bool型背包,相信大家都会做得对吧qwq
标签:-- 鄙视 选择 pop 浮点数 位置 can 没有 empty
原文地址:https://www.cnblogs.com/Hale522520/p/11541214.html