A 处女座的签到题
链接:https://ac.nowcoder.com/acm/contest/327/A
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
平面上有n个点,问:平面上所有三角形面积第k大的三角形的面积是多少?
输入描述:
第一行T,表示样例的个数。
对于每一组样例,第一行两个整数n和k,
接下来n行,每行两个整数x,y表示点的坐标
T<=80
3<=n<=100
-109<=x,y<=109
对于每一组样例,保证任意两点不重合,且能构成的三角形的个数不小于k
输出描述:
对于每一组样例,输出第k大三角形的面积,精确到小数点后两位(四舍五入)。
示例1
输入
复制
1
4 3
1 1
0 0
0 1
0 -1
输出
复制
0.50
说明
样例中一共能构成3个三角形,面积分别为0.5,0.5,和1,面积第3大的为0.5
分析:
nth_element是个好东西
官方题解:
由于题目条件,x,y坐标的绝对值均在1e9以下,面积可能会到达1e18,所以无法用double储存。三角形的面积等于相邻两边叉积的一半,所以三角形面积的两倍一定是整数,我们可以用long long来储存,最后特判输出”.00”或”.50”。
对于找第k大,时间复杂读为O(n),可以利用快排的思想或者利用nth_element。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int t,n,k;
struct point
{
ll x,y;
} a[105];
int main()
{
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&n,&k);
for (int i=1; i<=n; i++)
{
scanf("%lld%lld",&a[i].x,&a[i].y);
}
vector<ll> v;
for (int i=1; i<=n; i++)
{
for (int j=i+1; j<=n; j++)
{
for (int w=j+1; w<=n; w++)
{
ll area=abs((a[j].x-a[i].x)*(a[w].y-a[i].y)-(a[w].x-a[i].x)*(a[j].y-a[i].y));
///求叉积,肯定为整数为三角形面积二倍
v.push_back(area);
}
}
}
nth_element(v.begin(),v.begin()+v.size()-k,v.end());
ll ans=v[v.size()-k];
if (ans%2==0)
printf("%lld.00\n",ans/2);
else
printf("%lld.50\n",ans/2);
}
return 0;
}
C处女座的砝码
链接:https://ac.nowcoder.com/acm/contest/327/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
处女座热爱做物理实验,为了实验,处女座必须要精确的知道物品的质量。处女座准备自己设计一套砝码,每一个砝码都是正整数,这套砝码必须能够精确测量出n以内所有正整数的质量,处女座想要知道至少需要多少个砝码。你可以在天平的任意一边放置砝码。
输入描述:
一行,一个正整数n
1<=n<=101000
输出描述:
一个整数,表示最少的砝码数。
示例1
输入
复制
20
输出
复制
4
说明
你可以选择1,2,6,11
1=1
2=2
3=1+2
4=6-2
5=6-1
6=6
7=6+1
8=6+2
9=6+2+1
10=11-1
11=11
12=11+1
13=11+2
14=11+2+1
15=11+6-2
16=11+6-1
17=11+6
18=11+6+1
19=11+6+2
20=11+6+2+1
分析:结论题:3^k>=2*n+1
官方题解
python太秀了
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
BigInteger n =in.nextBigInteger();
n=n.multiply(new BigInteger("2"));
n=n.add(new BigInteger("1"));
int l=1,r=3000;
BigInteger three=new BigInteger("3");
while(l<r) {
int mid=(l+r)>>1;
if(three.pow(mid).compareTo(n)<0) {
l=mid+1;
}
else
{
r=mid;
}
}
System.out.println(l);
}
}
import math
n = int(input())
print(math.floor(math.log(2 * n - 1) / math.log(3)) + 1)
G处女座与复读机
链接:https://ac.nowcoder.com/acm/contest/327/G
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
一天,处女座在牛客算法群里发了一句“我好强啊”,引起无数的复读,可是处女座发现复读之后变成了“处女座好强啊”。处女座经过调查发现群里的复读机都是失真的复读机,会固定的产生两个错误。一个错误可以是下面的形式之一:
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就有可能是复读机。
分析:
暴力和DP都能解:
暴力解法:
两步变换可以看成不小于两步变换
1. 相同,那么可以把一个字母改成错误的再改成对的
2. 改变一个字母,可以把这个字母改成错误的再改成对的
3. 增加一个字母,可以增加一个错误的字母再改成对的
4. 减少一个字母,可以先把这个字母改变再删除这个字母
然后只需要暴力所有情况即可,复杂度O(n^3)
DP解法:
我们定义dp[i][j]表示从字符串1的前i个字符转移到字符串2的前j个字符至少需要几步
DP方程则为:
dp[i][j]=min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+flag));
方程解释:
1.dp[i-1][j]+1表示字符串1的前i个字符加1个字符到字符串2前j个字符
2.dp[i][j-1]+1表示字符串1的前i个字符-1个字符到字符串2前j个字符
3.if(s1[i]==s2[j])
dp[i-1][j-1]=dp[i][j]
else
dp[i-1][j-1]+1表示字符串1的前i个字符修改1个字符到字符串2前j个字符
暴力代码(标程)
#include <bits/stdc++.h>
using namespace std;
string a,b;
int main()
{
cin>>a>>b;
if (fabs((int)a.length()-(int)b.length())>2)
{
puts("NO");
}
else
{
if (b.length()==a.length()+2)
{
int can=0;
for (int i=0;i<b.length();i++)
{
for (int j=i+1;j<b.length();j++)
{
string s="";
for (int k=0;k<b.length();k++)
{
if (k!=i && k!=j) s.push_back(b[k]);
}
if (a==s) can=1;
}
}
if (can==1) puts("YES");
else puts("NO");
}
else if ((int)b.length()==(int)a.length()-2)
{
swap(a,b);
int can=0;
for (int i=0;i<b.length();i++)
{
for (int j=i+1;j<b.length();j++)
{
string s="";
for (int k=0;k<b.length();k++)
{
if (k!=i && k!=j) s.push_back(b[k]);
}
if (a==s) can=1;
}
}
if (can==1) puts("YES");
else puts("NO");
}
else if (b.length()==a.length()+1)
{
int can=0;
for (int i=0;i<b.length();i++)
{
string s="";
for (int j=0;j<b.length();j++)
{
if (j!=i) s.push_back(b[j]);
}
int cnt=0;
for (int i=0;i<a.length();i++)
{
if (a[i]!=s[i]) cnt++;
}
if (cnt<=1) can=1;
}
if (can==1) puts("YES");
else puts("NO");
}
else if ((int)b.length()==(int)a.length()-1)
{
swap(a,b);
int can=0;
for (int i=0;i<b.length();i++)
{
string s="";
for (int j=0;j<b.length();j++)
{
if (j!=i) s.push_back(b[j]);
}
int cnt=0;
for (int i=0;i<a.length();i++)
{
if (a[i]!=s[i]) cnt++;
}
if (cnt<=1) can=1;
}
if (can==1) puts("YES");
else puts("NO");
}
else
{
int can=0;
for (int i=0;i<b.length();i++)
{
for (int j=i+1;j<b.length();j++)
{
int cnt=0;
for (int k=0;k<b.length();k++)
{
if (k==i || k==j) continue;
if (a[k]!=b[k]) cnt++;
}
if (cnt==0) can=1;
}
}
for (int i=0;i<b.length();i++)
{
for (int j=0;j<b.length();j++)
{
string s="";
string t="";
for (int k=0;k<b.length();k++)
{
if (k!=i) s.push_back(a[k]);
}
for (int k=0;k<b.length();k++)
{
if (k!=j) t.push_back(b[k]);
}
if (s==t) can=1;
}
}
if (can==1) puts("YES");
else puts("NO");
}
}
return 0;
}
DP代码
#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
const int maxn=105;
int dp[maxn][maxn];
char s[maxn],t[maxn];
int main(){
scanf("%s %s",s+1,t+1);
int len1=strlen(s+1),len2=strlen(t+1);
///dp[i][j]表示从字符串1的前i个字符转移到字符串2的前j个字符至少需要几步
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++)
dp[i][j]=INF;
}
for(int i=1;i<=len1;i++)
dp[i][0]=i;
for(int j=1;j<=len2;j++)
dp[0][j]=j;
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++)
{
int flag=1;
if(s[i]==t[j]) flag=0;
dp[i][j]=min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+flag));
}
}
if(dp[len1][len2]<=2)
printf("YES\n");
else printf("NO\n");
}
H 处女座的测验(一)
链接:https://ac.nowcoder.com/acm/contest/327/H
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
处女座进行了一场c语言的考试,要求很简单,输出2000个正整数,并且满足以下条件:
1. 任意两个数互质
2. 任意两个数x,y,满足,其中
为n的因子的个数
举例:6的因子有1,2,3,6,所以τ(6)=4τ(6)=4
输入描述:
本题没有输入
输出描述:
2000行,每行一个正整数
输出的每个整数都必须在1-4*108之间
如果有多组答案,输出任意一组即可。
分析:我们知道一个质数怕p1有两个因子,两个质数p1,p2相乘有四个因子:1,p1,p2,p1*p2
....所以四个质数相乘就会有16个因子,即我们用x=p1*p2,y=p3*p4,我们用四千个质数就可以构造2000个这样的数。但要第一个乘以第4000个,可以算出
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 20007
using namespace std;
typedef long long ll;
const int MAXN =40000;
bool flag[MAXN];
int primes[MAXN/3],pi;
void Prime()
{
int i,j;
pi=0;
memset(flag,false,sizeof(flag));
for(i=2;i<MAXN;i++)
{
if(!flag[i]) primes[++pi] = i;
for(j=1;(j<=pi)&&(i*primes[j]<MAXN);j++)
{
flag[i*primes[j]]=true;
if (i%primes[j]==0)
break;
}
}
}
int main()
{
Prime();
int cnt=0;
int num=0;
for(int i=1;i<=2000;i++)
{
ll ans=primes[i]*primes[4001-i];
cout<<ans<<endl;
}
return 0;
}
J处女座的期末复习
链接:https://ac.nowcoder.com/acm/contest/327/J
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
快要期末考试了,处女座现在有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门课
备注:
考试时不能复习,保证考试时间不会重叠。
复习可以拆开,只要复习时间够了即可。
分析:数据比较水
贪心做法, 每次复习还没有复习但是最先考试的科目即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define N 500010
#define ll long long
using namespace std;
ll n,m;
struct node
{
ll s,e;
}a[N];
bool cmp(node a,node b)
{
return a.e<b.e;
}
int main()
{
scanf("%lld",&n);
for (int i=1;i<=n;i++)
{
scanf("%lld",&a[i].s);
}
for (int i=1;i<=n;i++)
{
scanf("%lld",&a[i].e);
}
sort(a+1,a+n+1,cmp);
int t=0;
int flag=1;
int j=1;
int i=1;
for(i=1;i<=n;i++)
{
t+=a[i].s;
if(t>a[i].e)
{
cout<<"NO"<<endl;
return 0;
}
t+=2;
}
cout<<"YES"<<endl;
return 0;
}