1、处女座与重修费
题目描述
期末考试结束了,处女座发现很多人挂了大物,只能等着第二年重修,还要交400元的重修费。处女座突然想起有个学长和他讲过,如果学校哪一年缺钱了,那一年的大物试卷就会特别难。现在处女座有了所有人的成绩,处女座想知道如果所有挂科的人都在第二年重修,学校能赚多少重修费?
挂科是指一门课的分数小于60分。
输入描述:
第一行一个整数n,表示考试的人数。
第二行n个整数,表示每个人的成绩。
1<=n<=10000
学生的成绩为0-100(包括0和100)之间的整数
输出描述:
一行,学校能赚的重修费用
示例1
输入
4
60
56
100
59
输出
800
这才是真正的签到题,没什么难度,给你点小自信假装很简单
#include
using namespace std;
int main()
{
int n,cnt=0;
cin>>n;
while(n--)
{
int temp;
cin>>temp;
if(temp<60)cnt++;
}
cout<
2、处女座的期末复习
题目描述
快要期末考试了,处女座现在有n门课程需要考试,每一门课程需要花ai小时进行复习,考试的起始时间为bi,处女座为了考试可以不吃饭不睡觉,处女座想知道他能否复习完所有的科目(即在每一门考试之前复习完该科目)。每一门课的考试时间都为两小时。
输入描述:
第一行一个整数n
第二行n个整数a1,a2,…,an,表示每门课需要复习的时间
第三行n个整数b1,b2,…,bn,表示每门课考试的时间
1<=n<=105
0<=ai<=109
0<=bi<=109
输出描述:
如果处女座能复习完,输出”YES”,否则输出”NO”
示例1
输入
3
0 1 1
2 6 4
输出
YES
说明
在0-1小时复习第2门课,
在1-2小时复习第3门课,
在2-4小时考第1门课,
在4-6小时考第3门课,
在6-8小时考第2门课
备注:
考试时不能复习,保证考试时间不会重叠。
复习可以拆开,只要复习时间够了即可。
一个比较基础的贪心算法题,先根据输入的数据sort一下,当考试时间相同时按照复习需要时间,不相同时按照考试时间排序,之后从最早考试的那一科开始,如果满足已经用的时间<=考试时间就说明可以满足条件,已经用的时间为考试时间加上复习时间。
AC代码如下
#include
using namespace std;
struct Node {
int time;
int rank;
};
struct Node N[100005];
long long int t;
bool cmp(struct Node a,struct Node b)
{
if(a.rank!=b.rank)
return a.rank>n;
t=0;
for(int i=0;i>N[i].time;
for(int i=0;i>N[i].rank;
sort(N,N+n,cmp);
int flag=1;
for(int i=0;i
另外还看了几道题,勉强知道考点,实在是打击人,主办方重新定义“基础”这个词语的意思,坐等题解吧。
3、处女座与宝藏
题目描述
处女座进行了一次探险,发现了一批宝藏。如果他获得这批宝藏,那么他一辈子都不需要工作了。但是处女座遇到了一个难题。
宝藏被装在n个宝箱里,宝箱编号为1,2,…,n,只有所有宝箱在某一时间被打开,处女座才能获得宝藏。有m个开关,每个开关控制k个宝箱,如果按下一个开关,那么这k个宝箱的开关状态都会发生改变(从开启变成关闭,从关闭变成开启),处女座想知道他能否获得这批宝藏。
输入描述:
第一行两个正整数n,m,
第二行n个整数,每个整数为0或1,表示初始时宝箱的状态,0表示开启,1表示关闭
接下来m行,每行开头一个整数k表示这个开关控制的宝箱的个数,接下来k个整数,表示控制宝箱的编号
1<=n,m<=200000
1<=k<=n
题目保证每个宝箱最多被两个开关控制。
输出描述:
一行,如果处女座能获得宝藏,输出”YES”,否则输出”NO”示例1
输入
4 4
1 0 1 1
2 3 4
2 1 3
1 2
2 1 2
输出
YES
一道2-SAT题目,头一次听说,研究了题解的代码研究了几个小时,勉勉强强看懂,用到了找有向图最大连通分量的方法,难度对菜鸡的我实在是太大了,具体都写在注释里了。
#include
using namespace std;
#define ll long long
const int MAXN = 400010;
const int MAXM = 800010;
struct Edge
{
int to,next;
}edge[MAXM];
int head[MAXN],tot;//tot用于记录当前存入的边数 ,head用于记录最后一个输入的以这个点为起点的边
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
bool Instack[MAXN];
int num[MAXN];
/*
DFN[ i ] : 在DFS中该节点被搜索的次序(时间戳)
LOW[ i ] : 为i或i的子树能够追溯到的最早的栈中节点的次序号
当DFN[ i ]==LOW[ i ]时,为i或i的子树可以构成一个强连通分量
*/
void Tarjan(int u)//用于找最大强连通分量
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;//用数组实现了一个堆栈
Instack[u] = true;//记录是否进栈
for(int i = head[u];i != -1;i = edge[i].next)
{
v = edge[i].to;//边的终点
if( !DFN[v] )//相当于进行了一次深搜
{
Tarjan(v);
if(Low[u] > Low[v])
Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;//全都出栈
Belong[v] = scc;//当前在堆栈中的节点全都在一个强连通分量中
num[scc]++;//记录当前强连通分量里面有多少个点
}
while(v != u);
}
}
bool solvable(int n)//n表示宝箱个数的两倍
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 0;i < n;i++)
if(!DFN[i])
Tarjan(i);//找出所有的强连通分量
for(int i = 0;i < n;i += 2)
if(Belong[i] == Belong[i^1])
return false;
return true;//只有在所有宝箱在一个连通分量中才可以满足条件
}
int n,m;
int a[200005];
vector v[200005];
int main()
{
scanf("%d%d",&n,&m);
init();
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);//记录初始状态
for (int i=0;i
4、处女座与复读机
题目描述
一天,处女座在牛客算法群里发了一句“我好强啊”,引起无数的复读,可是处女座发现复读之后变成了“处女座好强啊”。处女座经过调查发现群里的复读机都是失真的复读机,会固定的产生两个错误。一个错误可以是下面的形式之一:
1.将任意一个小写字母替换成另外一个小写字母
2.在任意位置添加一个小写字母
3.删除任意一个字母
处女座现在在群里发了一句话,他收到了一个回应,他想知道这是不是一个复读机。
输入描述:
两行
第一行是处女座说的话s
第二行是收到的回应t
s和t只由小写字母构成且长度小于100
输出描述:
如果这可能是一个复读机输出”YES”,否则输出”NO”
示例1
输入
abc
abcde
输出
YES
说明
abc->abcd->abcde
示例2
输入
abcde
abcde
输出
YES
说明
abcde->abcdd->abcde
备注:
只要能经过两步变换就从s得到t就有可能是复读机。
答案给出的是模拟的方法,很容易想明白,但是题目存在很多值得优化的地方,网上有大神用动态规划做的也AC,此外针对答案给出的代码,在循环结束的位置上还有可以优化的地方,下面代码是做了部分改动的AC代码,循环结束的条件加上&&can可以减少循环次数,此外还在变化一位的情况做了修改,应该是cnt==1时才符合条件,而不是cnt<=1,虽然效果是一样的。具体思路写在注释里了。
#include
using namespace std;
string a,b;
int main()
{
cin>>a>>b;
if (fabs((int)a.length()-(int)b.length())>2)//缩小范围,如果复读机说的比原话长度还要差别2位以上说明肯定不是
puts("NO");
else
{
if (b.length()==a.length()+2)//增加两位
{
int can=0;
for (int i=0;i