高精度1

// Vijos / 题库 /

水王争霸

sort在结构体排序中,可自定义。之前也知道可自定义,但没想到范围应用这么广!!!

这道题,长见识了。刚开始自定义排序,目前还没找到错误,但就是没过。。。

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 11000
struct BigNum
{
    int len;
    char num[maxn];
    char ID[maxn];
}n[maxn];
bool compare(BigNum a,BigNum b)
{
    if(a.len>b.len) return a.len>b.len;
    if(a.len==b.len){
        if(strcmp(a.num,b.num)==0){
                return strcmp(a.ID,b.ID)<0;
        }
        else return strcmp(a.num,b.num)>0;
    }
    return false;
}
int main()
{
    int m;
    cin>>m;
    for(int i=1;i<=m;i++)
    {
     cin
>>n[i].ID>>n[i].num; for(int j=0;n[i].num[j]!='\0';j++,n[i].len++); } sort(n+1,n+1+m,compare); for(int i=1;i<=m;i++) cout<<n[i].ID<<endl; return 0; }

Vijos / 题库 /

国王游戏

//贪心还不是很熟,回来再学习一下。这道题需要用贪心来证明一下

大佬写的证明,之前牛客网上一道题也是类似的证明:

vijos题解的第一版就是这位大佬写的证明,引用一下(证明可以学习一下,下一道题就把牛客上的题目引用一下):

###贪心证明
假设相邻的两个人左右手分别是(a, b), (A, B)。设a * b <= A * B,i之前所有人的左手乘积为S。i+1位置(A,B),  i位置为(a,b)
则,ans1 = max{S / b, S * a / B}
若交换
则,ans2 = max{S / B, S * A / b}
因为,a * b <= A * B
所以,S * a / B <= S * A / b
又因为,S / B <= S * a / B
所以,ans2 = S * A / b
ans1 = max{S / B[i], S * a / B}
所以,ans1 <= ans2

所以需要排序,自定义排序+sort

 再根据数据的范围来确定,n<=1000,a,b<=10000,数据的乘积最大值为10^12,所以高精*低精+高精除以低精

老实说,这道题可折煞我了;有人说这是道水题,但我还是涨知识了。学到了。。
刚开始看到贪心证明之后,没考虑那么多,直接以为最后一个就是解,殊不知最优解可能也在中间。~~~

#include<iostream> #include<queue> #include<cstring> #include<algorithm> using namespace std; #define maxn 11000 #define p 1e9 struct BigNum { long long left,right; }n[maxn]; long long m,max1[maxn]; struct Big{ int len; int num[maxn]; }; Big a,b,ans; bool compare(BigNum x,BigNum y) { return x.left*x.right<y.left*y.right; }//sort比较,进行排序 void multi(int h) { for(int i=0;i<a.len;i++) a.num[i]=a.num[i]*h; for(int i=0;i<a.len;i++) { a.num[i+1]+=a.num[i]/10; a.num[i]%=10; if(i==a.len-1&&a.num[i+1]) ++a.len; } }//高精乘以低精 void dev(int h) { int t=0; ans.len=a.len; for(int i=ans.len-1;i>=0;i--) { t=t*10+a.num[i]; ans.num[i]=t/h; t=t%h; } while(ans.len>1&&!ans.num[ans.len-1]) --ans.len; }//高精除以低精 bool com(Big x,Big y) { if(x.len<y.len) return 1; if(x.len==y.len) { for(int i=x.len-1;i>=0;i--) if(x.num[i]<y.num[i]) return 1; } return false; }//解也可能在中间,就需要进行比较 int main() { cin>>m;cin>>n[0].left>>n[0].right; for(int i=1;i<=m;i++) { cin>>n[i].left>>n[i].right; } sort(n+1,n+1+m,compare); int h=n[0].left;//国王在第一位不变 while(h) { a.len++; a.num[a.len-1]=h%10; h=h/10; } for(int i=1;i<m;i++)//寻找最优解 { multi(n[i].left); dev(n[i+1].right); if(com(b,ans)) { b.len=ans.len; for(int i=ans.len-1;i>=0;i--) b.num[i]=ans.num[i]; } } for(int i=b.len-1;i>=0;i--) cout<<b.num[i]; return 0; }

//题外题,下面就跟高精无关了,就是个贪心证明

链接:https://ac.nowcoder.com/acm/contest/3003/F
来源:牛客网

题目描述

牛牛和 牛可乐 面前有 n 个物品,这些物品编号为 1,2,…,n1,2,\dots,n1,2,,n ,每个物品有两个属性 ai,bia_i, b_iai,bi 。 
 
牛牛与 牛可乐会轮流从剩下物品中任意拿走一个, 牛牛先选取。 
 
设 牛牛选取的物品编号集合为 H,牛可乐选取的物品编号的集合为 T,取完之后,牛牛 得分为 ∑i∈Hai\sum_{i\in H} a_iiHai;而 牛可乐得分为 ∑i∈Tbi\sum_{i\in T} b_iiTbi。 
 
牛牛和 牛可乐都希望自己的得分尽量比对方大(即最大化自己与对方得分的差)。 
 
你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。
看题时自己坑自己,a,b是分别输入
假设牛牛选择ai,bi,牛可乐选择ai+1,bi+1,ai+bi<ai+1+bi+1
同上面的证明
#include<algorithm> #include<iostream> using namespace std; struct bel{ int a,b; int num; }B[1000000]; bool compare(bel x,bel y) { return x.a+x.b>y.a+y.b; }//排序 int main() { int n; cin>>n; for(int i=1;i<=n;i++) B[i].num=i,cin>>B[i].a; for(int i=1;i<=n;i++) cin>>B[i].b; sort(B+1,B+1+n,compare); for(int i=1;i<=n;i+=2) { cout<<B[i].num<<' '; } cout<<endl; for(int i=2;i<=n;i+=2) { cout<<B[i].num<<' '; } return 0; }
/ Vijos / 题库 /

大整数

二分+高精,让我想一会~~~

猜你喜欢

转载自www.cnblogs.com/Showend/p/12354348.html