T1:四操作
有一个n个元素的数列,元素的值只能是0 1 2三个数中的一个,定义四种操作,(1 i x)表示为把第i位替换成x,x也只能是0 1 2三个数中的一个,(2 i j)表示把第i个数到第j个数所有的元素值加1,并对3取模,(3 i j)表示把第i个数到第j个数之间的序列的颠倒顺序,(4 i j)表示查询第i个数到第j个数之间的序列是否存在三个或以上相同数,如果有,输出yes,否则输出no
输入:第一行输入n,接下来一行输入n个数,保证是0 1 2中的一个,第三行输入一个数q,表示操作个数,接下来q行输入q种操作 输出:每次第四次操作时,输出yes或者no 数据范围:不记得了
解:
模拟题:选择好数据结构——进行模拟操作:
//四种操作:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<string>
//n个元素的数列, 每个元素是 0/1/2
//总共如下4种操作:
//(1) "1 i x"——把第i个改成x
//(2) "2 i j"——把vec[i]-vec[j]统统+1 %3
//(3) "3 i j"——把vec[i]-vec[j]之间逆序
//(4) "4 i j"——查询vec[i]-vec[j]之间是否存在相同的3个以上数
//第4种中,如果 j-i+1 >=9,直接输出yes
using namespace std;void swap(int & a,int &b)
{int tmp = a;a = b;b = tmp;
}int main()
{//方法一:直接模拟 - 模拟法最重要的是,如何选择存储数据的结构//暴力:直接用vectorint n ;cin>>n;vector<int> vec(n+1,0); //干脆假设i,j下标都是从1开始for(int i = 1;i<=n;i++){cin>>vec[i];}int q;cin>>q;while(q--){int num1,num2,num3;cin>>num1>>num2>>num3;if(num1 == 1){vec[num2] = num3;}else if(num1 == 2){ for(int i = num2; i<=num3 ;i++){vec[i] = (vec[i]+1)%3;}}else if(num1 == 3){int i = num2;int j = num3;while(j > i){swap(vec[i],vec[j]);i++;j--;}}else if (num1 == 4){if(num3 - num2 + 1 >= 9){cout<<"yes"<<endl;}else{int flag = 0;int a[3] = {0};for(int i = num2;i<=num3;i++){a[vec[i]]++;if(a[vec[i]] >=3){cout<<"yes"<<endl;flag = 1;break;}}if(flag == 0){cout<<"no"<<endl;}}}}return 0;
}
T2:清华售货机
清华大学的自动售货机一共有 𝑛 种饮料出售,每种饮料有自己的售价,并在售货机上各有一个出售口。购买第 𝑖 种饮料时,可以在第 𝑖 个出售口支付 𝑎𝑖 的价格,售货机便会在下方的出货处放出对应的饮料。
又到了清凉的夏日,自动售货机为每种饮料各进货了1 瓶存储在其中,供同学购买。但是,自动售货机却出现了一些故障,它有可能会出货不属于这个出售口的饮料。
对于第 𝑖 个出售口,支付 𝑎𝑖 的价格购买后,如果饮料 𝑖 与饮料 𝑏𝑖 都有存货,有 𝑝𝑖 的概率出货饮料 𝑖 ,有 1−𝑝𝑖 的概率出货饮料 𝑏𝑖 。如果其中一个有存货,另一个已经没有存货,则将出货有存货的那一种饮料。如果两种饮料都没有存货,售货机将不会出货任何饮料并发出警报。**即便最后你没有获得任何饮料,也需要支付 𝑎𝑖 的价格 ** 。
长颈鹿下楼来到这台售货机前,希望能买到最近火爆全网的饮料 𝑥 ,此时售货机中 𝑛 种饮料都存货有 1 瓶。由于他知道售货机有问题,因此决定采取这样的策略来购买:
- 在 𝑛 个出售口中等概率选择一个出售口 𝑠 开始购买,支付这个出售口的价格 𝑎𝑠 并得到出货。
- 当得到想要的饮料 𝑥 时,停止购买流程,满意欢喜的离去。
- 当得到不想要的饮料 𝑦 时,继续在第 𝑦 个支付口购买,支付 𝑎𝑦 的价格并等待出货。
- 当售货机发出警报时,停止购买流程,灰心丧气的离去。
现在他希望你告诉他,他这一次购买过程期望支付的价钱数量是多少?
解:
思路很简单,利用vec容器,然后按照题目的 思路,找到2个递归出口,写出递归函数即可!
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<string>//售货机 -- 大概率是 模拟题
//一共n种饮料,第i个出售口售价ai
//每种饮料 只有 1 瓶
//故障!
//支付ai后,如果饮料i和饮料bi都有存货:pi概率获得饮料i,1-pi获得另一种
//一种就直接出,否则什么都没有//策略:
//等概率的选择一个出售口s,并以as支付
//直到获取y
//或者没有出货
//根据输入数据,计算输出一个期望的 价格?using namespace std;int x= 0;
int n;struct drink
{double a; //价格int b; //另一个饮料的编号 - 下标从1开始用double p; //抽中i的概率int flag = 0; //flag = 0代表 这个i饮料还在//默认构造:drink(){this->flag= 0;this->a = 0; this->b =0; this->p = 0;}
};vector<drink> vec; //全局//处理输入:
void init()
{cin>>n>>x;drink tmp2;vec.push_back(tmp2); //index==0位置不用for(int i =1 ;i <=n;i++){drink tmp;cin>>tmp.a>>tmp.b>>tmp.p;vec.push_back(tmp);}
}//递归函数:func
double func(int i)
{double pi = vec[i].p;double ai = vec[i].a;int bi = vec[i].b;double ans = ai; //因为这一次选择了ai,一定会有一个基础的ai的钱需要花//选择第i个出货口后,进行递归模拟,出口是命中x或者i和bi都没了//case1:if(vec[i].flag == 0 && vec[bi].flag == 0){//i 和 bi都还在:double ans1 = 0;double ans2 = 0;//出货了 饮料i:vec[i].flag = 1;if(i == x){//ans1 = pi*ai;ans1 = 0;}else{ans1 = pi*func(i);}//出货了 饮料bivec[i].flag = 0; //补货vec[bi].flag = 1; //出货if(bi == x){//ans2 = (1-pi)*ai;ans2 = 0;}else{ans2 = (1-pi)*func(bi);}//-返回://flag 改回去:vec[i].flag = 0;vec[bi].flag = 0;ans = ans + ans1 + ans2;return ans;}//case2:if(vec[i].flag == 0 && vec[vec[i].b].flag != 0){//只有 饮料i在 - 必定是出饮料i://如果饮料i 不是x 就必定凉凉:if(x == i){return ans;}else{ans = ans + ai;return ans;}}//case3:if(vec[i].flag != 0 && vec[vec[i].b].flag == 0){//此时bi可能需要进行递归:if(bi == x) {return ans;}else{vec[bi].flag = 1; //此时bi已经出货了ans = ans + func(bi);//记得返回之前完成补货:vec[bi].flag = 0;return ans;}}//case4:if(vec[i].flag != 0 && vec[vec[i].b].flag != 0){return ans;}}int main()
{init();//开启模拟double p0 = (double)(1/(double(n)));double myans = 0;for(int i = 1 ; i <=n ;i++){myans = myans + p0*func(i);}cout<<myans<<endl;return 0;
}