题目描述 我们如何评价科学家的成功?根据发表论文的数量或其引用分数——更准确地说,被引用的次数?这两个要素都很重要。如果一篇论文被其他科学家的论文总共引用了C次,那么这篇论文的引用分数为C。科学家成功的一个可能衡量标准是他们的H指数,它同时考虑了论文数量和引用分数。 科学家的H指数定义为具有以下性质的最大整数H:科学家可以选择H篇论文,满足这H篇论文的引用分数都不小于H。例如,如果一个科学家写了10篇论文,并且每一篇都被引用了至少10次,那么他的H指数(至少)是10。 写一个程序,输入某个科学家所有论文的引用分数,输出他的H指数。 输入 第一行输入包含整数N(1≤N≤5*1e5)。表示论文的数量。 第二行输入包含N个自然数Ci(Ci≤1e6)。表示每篇论文的引用分数。 输出 输出一个整数。表示这名科学家的H指数。 样例 样例输入1 5 1 1 4 8 1 样例输出1 2 样例输入2 5 8 5 3 4 10 样例输出2 4
此题比较轻松,和大众做法不同,我并没有排序,我用了一个cnt统计数字出现次数,然后倒着来找符合条件的,即积分为i满足能选i篇积分至少为i的。
题目描述 一个房间里有N张桌子,从左到右排成一行。有些桌子上有电话,而有些桌子是空的。所有的电话都坏了,所以当第i个办公桌上的电话响了,第j个办公桌上的电话也会响,如果第j个办公桌和第i个办公桌的距离不超过D。换句话说,j和i满足|j-i|≤D。第一张桌子和最后一张桌子上一定会有电话。开始的时候,最左边的桌子上的电话会响起。求要让最后一个电话响起,至少要在多少张办公桌上放置新电话? 输入 第一行输入包含两个整数N(1≤N≤3e5)和D(1≤D≤N)。分别表示办公桌的数量和题目中提到的距离。 第二行输入包含了N个整数Ai(0≤Ai≤1)。第i个整数Ai表示第i个张桌子的状态。具体来说,如果Ai=1那么第i张桌子上有电话,如果Ai=0那么第i张桌子上没有电话。 输出 输出一个整数。表示需要放置新电话的数量。 样例 样例输入1 4 1 1 0 1 1 样例输出1 1 样例输入2 5 2 1 0 0 0 1 样例输出2 1 样例输入3 8 2 1 1 0 0 1 0 0 1 样例输出3 2
感觉就是一道贪心模拟,我们就直接保证放到最远即可,中途有一些电话线的话,我们就重新开始算。
题目描述 年轻的Jozef得到了一个由2的N次方个正整数组成的集合作为礼物。考虑到Jozef经常参加足球锦标赛,他决定为这2的N次方个正整数组织一个锦标赛。 数字锦标赛如下图所示。比赛成对进行,两个数字中较高的一个前进到更高级别。比赛的级别用1到N之间的数字表示,其中最高的级别用数字0表示。 由于Jozef没有时间组织所有的比赛,他想知道,对于集合中的每个数字,在所有的对阵安排中,能达到的最高级别(数字最小的级别)。 输入 第一行输入包含一个整数N(1≤N≤20)。表示题目中提到的N。 第二行输入包含了2的N次方个正整数Ai(Ai≤1e9)。表示集合中2的N次方个正整数。 输出 输出一行包含2的N次方个整数。其中第i个数表示按照输入的顺序集合中的第i个正整数能达到的最高级别。 样例 样例输入1 2 1 4 3 2 样例输出1 2 0 1 1 样例输入2 4 5 3 2 6 4 8 7 1 2 4 3 3 6 4 8 1 样例输出2 1 2 2 1 1 0 1 3 2 1 2 2 1 1 0 3 样例输入3 1 1 1 样例输出3 0 0
先说一下题意吧,可能有人觉得样例不对,毕竟当时我一开始也理解错了。 简单来说,他就是让你自己安排,求每一个数最远能到哪。 那我们肯定要排序啊。a的值很大,我们进行离散。 这里有一点是相同的数也可以晋级。所以怎么算其能到达的最远呢。 这里呢,可以找一下规律。 如果i可以到n - 1,那么肯定要有至少2个小于等于i的数。 如果i可以到n - 2,那么肯定要有至少4个小于等于i的数。 如果i可以到n - k,那么肯定要有至少2^k个小于等于i的数。 就这样完了,处理你自己弄一下差不多了。
题目描述 如果一个数等于它的所有因数(小于自身的)之和,那么这个数就是完美的。例如,28是完美的,因为28=1+2+4+7+14。
基于这个定义,我们数字n的不完美度定为f(n),它等于n与n的所有因数(小于n的)之和的差的绝对值,因此完美数的不完全度为0,其余自然数的不完全度都大于0。 例如:
●f(6)=|6-(1+2+3)|=0 ●f(11)=|11-(1)|=10 ●f(24)=|24-(1+2+3+4+6+8+12)|=|-12|=12
写一个程序,对于正整数A和B,计算A和B之间所有数字的不完美度之和:即f(A)+f(A+1)+…+f(B)。 输入 第一行输入包含两个整数A和B(1≤A≤B≤1e7)。表示题目中的A和B。 输出 输出一个整数。表示f(A)+f(A+1)+…+f(B)。 样例 样例输入1 1 9 样例输出1 21 样例输入2 24 24 样例输出2 12
其实这是一道求约数和的模板题,不完美度这玩意你求出约数和你就可以O(1)时间内求解。 约数和应该来说是有两种求法,第一种便是nlog(n)的求法,代码简短。第二种则是欧拉筛法的求法,代码略长一点,时间复杂度为O(n)。 但考试时限3s,好像nlog(n)并不会爆,评测也过了。但OJ上TLE了,所以还是用欧拉筛吧
题目描述 Daniel有一袋糖果和N张卡片。
每张卡片上都写有一个正整数Pi。丹尼尔在吃糖果的时候,想到了一个有趣的游戏。Daniel可以挑选两张卡片,将它们绑在一起,如果Daniel挑选第a张牌和第b张牌,那么Daniel会马上吃掉min(Pa%Pb,Pb%Pa)个糖果,其中x%y表示x除以y的余数。
Daniel每次会挑选两张卡片将它们绑在一起,最终,当他提起其中一张卡片时,所有其余的卡片也会被提起。他可以多次将同一张卡片和其他卡片绑在一起。Daniel要求你计算他至少要吃多少糖果。 输入 第一行输入包含一个整数N(1≤N≤1e5)。表示卡片的数量。
接下来N行每行包含一个正整数Pi(Pi≤1e7)。第i个整数Pi表示第i张卡片上的正整数。 输出 输出一个整数。表示Daniel至少要吃多少糖果。 样例 样例输入1 4 2 6 3 11 样例输出1 1 样例输入2 4 1 2 3 4 样例输出2 0 样例输入3 3 4 9 15 样例输出3 4
一看也知道是一道最小生成树。然而数据太大了,用裸的最小生成树跑不仅会超时还会爆空间,可怕可怕。 正解其实就是最小生成树加优化。 首先,如果存在倍数关系,连边的花费就为0,我们可以缩点,但有一点要注意。不能够强行把这个点删去,我们把它放在一个集合中即可。强行删去会使得答案有误,其它点有可能与另一个点的倍数连边。列如3,11,22. 然后就是删边,我们要保存有意义的边。一些肯定用不上的边一定要删去。 我们定义一个数组q,q[i]则表示大于等于i的最小的数(原数列出现过)。 处理到一个点我们便可以枚举这一个值的倍数,至于那三个数的推导,给个链接但其实还有一个问题,那就是枚举倍数时这样加会有重复的边出现,我们仅仅需要存一个,就需要判断一下,看下一次塞进去的是不是与此相等。还有一点是,先处理判断一下q[p[i] + 1],然后再从2*p[i]开始枚举。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<queue> #define P 10000005 #include<cstdlib> using namespace std; struct node { int u,v,w; node (){}; node (int U,int V,int W){ u = U,v = V,w = W; } bool operator < (const node &a)const { return w < a.w; } }; int n,p[P],cnt,fa[P],q[P],flag[P],maxn,a[P],k,n1; bool vis[P]; vector <node>s; void makeset(int x){ for (int i = 1;i <= x;i ++) fa[i] = i; } int findset(int x){ if (fa[x] != x) fa[x] = findset(fa[x]); return fa[x]; } int main(){ scanf ("%d",&n); for (int i = 1;i <= n;i ++){ scanf ("%d",&p[i]); maxn = max(p[i],maxn); q[p[i]] = p[i]; flag[p[i]] = i; } makeset(maxn); for (int i = maxn;i >= 0;i --) if (!q[i]) q[i] = q[i + 1]; for (int i = 1;i <= n;i ++){ for (int j = p[i] * 2;j <= maxn;j += p[i]){ if (flag[j]){ int t1 = findset(p[i]); int t2 = findset(j); if (t1 != t2){ fa[t2] = t1; k ++; } } } } for (int i = 1;i <= n;i ++){ if (!vis[p[i]]){ vis[p[i]] = 1; int t1 = findset(p[i]); if (p[i] + 1 > maxn || (q[p[i] + 1] != q[p[i] + p[i]] && findset(q[p[i] + 1]) != t1)) s.push_back(node(p[i],q[p[i] + 1],q[p[i] + 1] % p[i])); for (int j = p[i] * 2;j <= maxn;j += p[i]){ if (j + p[i] > maxn || (q[j] != q[j + p[i]] && findset(q[j]) != t1)){ s.push_back(node(p[i],q[j],q[j] % p[i])); } } } else n1 ++; } sort(s.begin(),s.end()); long long mst = 0; for (int i = 0;i < s.size() && k < n - n1 - 1;i ++){ int t1 = findset(s[i].u); int t2 = findset(s[i].v); if (t1 != t2){ if (t1 < t2) fa[t2] = t1; else fa[t1] = t2; mst += s[i].w; k++; } } printf("%lld\n",mst); }