D.O(n!)
https://ac.nowcoder.com/acm/contest/911/D
题目给你n件商品,每件商品有两个属性,a是商品的原价格,p是买了这件商品之后其他没买的商品的价格就要乘上这个买了的商品的p值。因为要求最小花费,所以如果这件商品的p的对另外的商品的价值影响大于另外的商品的p值对这件商品的价值影响就先买这件商品,我们通过这个来排一次序就行了。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main {
static class price implements Comparable<price>{
double a,p;
public price(double a, double p) {
super();
this.a = a;
this.p = p;
}
@Override
public int compareTo(price p) {
if(this.a*(1-p.p)>p.a*(1-this.p)){
return 1;
}else if(this.a*(1-p.p)<p.a*(1-this.p)){
return -1;
}else{
return 0;
}
}
}
static price pr[]=new price[100010];
static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static void main(String[] args) {
int n=nextInt();
double a,p;
for(int i=0;i<n;i++){
a=nextDouble();
p=nextDouble();
pr[i]=new price(a,p);
}
Arrays.sort(pr,0,n);
double sum=0;
double pp=1;
for(int i=0;i<n;i++){
sum+=pr[i].a*pp;
pp*=pr[i].p;
}
System.out.printf("%.6f",sum);
}
static double nextDouble(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return st.nval;
}
static int nextInt(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return (int) st.nval;
}
}
E.斐波那契串
https://ac.nowcoder.com/acm/contest/911/E
这题还不是很理解,只是照着c通过的代码改的一份
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
static final int N=(int) (1e4+7);
static long f[]=new long[N];
static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args) {
String s[]=new String[3];
s[1]=next();
s[2]=next();
f[1]=s[1].length();
f[2]=s[2].length();
int k=0;
for(int i=3;f[i-1]<=1e18;i++){
f[i]=f[i-1]+f[i-2];
k=i;
}
int q=nextInt();
long x,y;
while(q-->0){
x=nextLong();
y=nextLong();
if(x>2)
x=lower_bound(f, 1, k, y); //之前我的lower_bound函数写的有点问题,然后一直没有返回。。结果tle了
while(x>2){
if(y<=f[(int) (x-1)])
x--;
else{
y-=f[(int) (x-1)];
x-=2;
}
}
out.println(s[(int) x].charAt((int) (y-1)));
}
out.flush();
}
static int lower_bound(long arr[],int l,int r,long target){
while(l<r){//之前我的条件是l<=r,结果就一直没能跳出循环
int mid=l+(r-l)/2;
if(arr[mid]>=target){
r=mid;
}else{
l=mid+1;
}
}
return l;
}
static String next(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return st.sval;
}
static int nextInt(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return (int)st.nval;
}
static long nextLong(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return (long)st.nval;
}
}
F.无交集的圆
https://ac.nowcoder.com/acm/contest/911/F
问你圆心在y轴上的n个圆两两不相交的组合个数,一个圆告诉了你圆心和半径,那这个圆的上边界和下边界也就知道了,我们存储结构体的形式来存一个圆,存它的上下边界,然后按照下边界从小到大排序。然后按顺序枚举每一个圆的上边界,找到第一个满足下边界高于这个上边界的圆,返回数组下标i,这里我们要用二分查找,不然会超时。这样我们的结果就是ans+=n-i;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main {
static class circle implements Comparable<circle>{
double y,r_x,r_s;
public circle(double y, double r_x, double r_s) {
super();
this.y = y;
this.r_x = r_x;
this.r_s = r_s;
}
@Override
public int compareTo(circle c) {
if(this.r_x>c.r_x){
return 1;
}else if(this.r_x==c.r_x){
return 0;
}else{
return -1;
}
}
}
static circle cle[]=new circle[100010];
static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static void main(String[] args) {
int n=nextInt();
double p,r;
for(int i=0;i<n;i++){
p=nextDouble();
r=nextDouble();
cle[i]=new circle(p,p-r,p+r);
}
Arrays.sort(cle,0,n);
long ans=0;
for(int i=0;i<n;i++){
int num=search(0,n-1,i,cle);
ans+=n-num;
}
System.out.println(ans);
}
static int search(int l,int r,int k,circle temp[]){
while(l<=r){
int mid=(l+r)>>1;
if(temp[mid].r_x>temp[k].r_s)
r=mid-1;
else
l=mid+1;
}
return l;
}
static double nextDouble(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return st.nval;
}
static int nextInt(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return (int) st.nval;
}
}
H.虚无的后缀
https://ac.nowcoder.com/acm/contest/911/H
这题问你n个数中选k个数相乘起来后缀0的个数最多是多少。而要求后缀0的个数,其实就是求看每个数能分解成几个2,几个5,取其中的小值就是后缀0的个数。比如5里面有0个2,1个5,所以5有0个后缀0,比如20里面有2个2,1个5,所以20有1个后缀0,当5乘以20时,总共就有0+2个2,1+1个5,所以5乘以20有2个后缀0.
再看这题,我们就可以先把所有的数中的2的个数,5的个数算出来,分别加起来。
然后再减去其中n-k个数让后缀0最多。两个for循环,第一层遍历要减去的数的个数,第二层遍历所有没有被减去的数看减去哪个数后缀0减少的最少。
import java.util.Scanner;
//先把所有的数都算上,然后减去n - k个数
public class Main {
static int dp[][]=new int[205][10000];
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n,k;
n=sc.nextInt();
k=sc.nextInt();
long a;
int sum2=0;
int sum5=0;
long ans[][]=new long[n][2];//ans[i][0]代表第i个数有多少个2,ans[i][1]代表第i个数有多少个5
boolean vis[]=new boolean[n];
for(int i=0;i<n;i++){
a=sc.nextLong();
while(a%2==0){
a/=2;
sum2++;
ans[i][0]++;
}
while(a%5==0){
a/=5;
sum5++;
ans[i][1]++;
}
}
for(int i=0;i<n-k;i++){
long ma=0;
int pos=0;
for(int j=0;j<n;j++){
if(!vis[j]){
long tmp=Math.min(sum2-ans[j][0],sum5-ans[j][1]);
if(tmp>ma){
ma=tmp;
pos=j;
}
}
}
vis[pos]=true;
sum2-=ans[pos][0];
sum5-=ans[pos][1];
}
System.out.println(Math.min(sum2, sum5));
sc.close();
}
}
J.异或和路径
https://ac.nowcoder.com/acm/contest/911/J
第一次做这种类型的题,赛后看了其他人的通过代码,慢慢学习 ^ _ ^
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
//跑一遍dfs求出每个点到根的路径异或和,然后按二进制数位算贡献度
public class Main {
static long mod=1000000007;
static int maxn=(int) (1e5+15);
static int p[]=new int[maxn];
static int n,eid,u,v,val;
static class edge{
int v,next,w;
public edge(int v, int next, int w) {
super();
this.v = v;
this.next = next;
this.w = w;
}
}
static edge e[]=new edge[maxn<<1];
static void insert(int u,int v,int w){
e[eid]=new edge(v,p[u],w);
p[u]=eid++;
}
static void init(){
Arrays.fill(p, -1);
eid=0;
}
static long a[]=new long[maxn];
static long num[]=new long[65];
static long res=0;
static void dfs(int u,int fa){
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==fa)
continue;
a[v]=a[u]^e[i].w;
dfs(v,u);
}
}
static StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static void main(String[] args) {
init();
n=nextInt();
for(int i=1;i<n;i++){
u=nextInt();
val=nextInt();
insert(i+1,u,val);
insert(u,i+1,val);
}
dfs(1,0);
for(int i=1;i<=n;i++){
for(int j=0;j<60;j++){
if((a[i]&(1<<j))!=0)//判断所有点加起来每个位上有多少个1
num[j]++;
}
}
for(int i=0;i<60;i++){
res+=(1<<i)%mod*num[i]%mod*(n-num[i])%mod;//异或求和公式
res%=mod;
}
System.out.println(res);
}
static int nextInt(){
try {
st.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return (int)st.nval;
}
}