2018多校第一场

1001:Maximum Multiple

思路:根据题意,设\frac{n}{x}=a,\frac{n}{y}=b,\frac{n}{z}=c,易推导出来\frac{1}{a}+\frac{1}{b}+\frac{1}{c}=1,这样a,b,c的取值范围就只有有限的3,3,3和2,4,4和2,3,6这三种取法,并且2,3,6是不如前两种取法,所以答案就是min\left\{\frac{n^3}{abc}\right\}

代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int t;scanf("%d",&t);
    while(t--){
        long long n;scanf("%lld",&n);
        if(n%3==0)printf("%lld\n",n*n*n/27);
        else if(n%4==0)printf("%lld\n",n*n*n/32);
        else printf("-1\n");
    }
}

1002:Balanced Sequence

思路:谜之排序。。。正确的排序应该是先分类(左括号多还是右括号多),然后对同一类的在比较(左括号多的,比较右括号少的放前面;右括号多的,比较左括号少的放前面)。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
    int a,b;
    bool operator < (const node & p)const {
        if(b>=a && p.b<p.a)return false;
        if(b<a && p.b>=p.a)return true;
        if(b>=a && p.b>=p.a)return a>p.a;
        return b<p.b;
    }
};

vector<node>v;
char s[maxn];int ans=0;

void solve()
{
    int len=strlen(s);int ll=0,rr=0;
    for(int i=0;i<len;i++){
        if(s[i]=='(')ll++;
        if(s[i]==')'){
            if(ll!=0){
                ll--;ans+=2;
            }
            else rr++;
        }
    }
    v.push_back((node){ll,rr});
}

int main()
{
    //freopen("1002.in","r",stdin);
    //freopen("1002me.out","w",stdout);
    int t;scanf("%d",&t);
    while(t--){
        int n;scanf("%d",&n);v.clear();ans=0;
        for(int i=1;i<=n;i++){
            scanf("%s",s);solve();
        }
        sort(v.begin(),v.end());
        int left=0,right=0;
        for(int i=0;i<n;i++){
            int k=min(left,v[i].b);ans+=k*2;
            left=left+v[i].a-k;
            right=right+v[i].b-k;
        }
        printf("%d\n",ans);
    }
}

1003:Triangle Partition

思路:先按x排序,再按y排序,然后依次每三个点输出一行。

代码:

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int x,y,id;
    bool operator < (const node & a)const {
        return x==a.x?y<a.y:x<a.x;
    }
};
vector<node>v;

int main()
{
    int t;scanf("%d",&t);
    while(t--){
        int n;scanf("%d",&n);v.clear();
        for(int i=1;i<=n*3;i++){
            int x,y;scanf("%d%d",&x,&y);
            v.push_back((node){x,y,i});
        }
        sort(v.begin(),v.end());
        for(int i=1;i<=n;i++){
            printf("%d %d %d\n",v[(i-1)*3].id,v[(i-1)*3+1].id,v[(i-1)*3+2].id);
        }
    }
}

1004:Distinct Values

思路:优先队列暴力放入,模拟,不过好像会T,但是用set就不会T。。。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
pair<int,int>p[maxn];
int ans[maxn];
set<int>s;
bool cmp(pair<int,int> a,pair<int,int>b)
{
    return a.first==b.first?a.second>b.second:a.first<b.first;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        int n,m;scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++){
            int l,r;scanf("%d%d",&l,&r);
            p[i]=make_pair(l,r);
        }
        sort(p,p+m,cmp);s.clear();memset(ans,0,sizeof ans);
        for(int i=1;i<=n;i++)s.insert(i);
        int k=0,fi=1,prel=0,prer=0;
        while(k<m){
            int l=p[k].first,r=p[k].second;k++;
            if(prel!=0 && prer!=0){
                if(prer>=l && r>prer){
                    for(int i=prel;i<l;i++)s.insert(ans[i]);
                }
                else if(l>prer){
                    for(int i=prel;i<=prer;i++)s.insert(ans[i]);
                }
            }
            if(ans[l]!=0 && ans[r]!=0)continue;
            prel=l,prer=r;
            if(ans[l]==0 && ans[r]==0){
                while(fi<l){ans[fi]=1;fi++;}
                while(fi<=r){ans[fi]=*s.begin();s.erase(s.begin());fi++;}
            }
            else if(ans[l]!=0 && ans[r]==0){
                while(fi<=r){ans[fi]=*s.begin();s.erase(s.begin());fi++;}
            }
        }
        while(fi<=n){ans[fi]=1;fi++;}
        for(int i=1;i<n;i++)printf("%d ",ans[i]);
        printf("%d\n",ans[n]);
    }
}

1005:Maximum Weighted Matching

不会

1006:Period Sequence

不会

1007:Chiaki Sequence Revisited

思路:先打表,然后找规律。我找的规律是:设n是需要求的值,2^k是小于n的最大值,那么S(n)=S(2^k)+S(n-2^k+1)+2^{k-1}*(n-2^k),在计算n=2^k时,S(2^k)还需要减一。所以我是先暴力找出2的n次幂的值,一共62个,然后用S(n)的算法去递归求出答案。

代码:

#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long a[100];long long id[100];

long long solve(long long x)
{
    long long ans=0;
    int k=-1;
    for(int i=0;i<=62;i++){
        if(id[i]<=x)k=i;
    }
    if(id[k]==x)return a[k];
    ans=a[k];
    long long tk=id[k-1],f=x-tk*2;
    long long ad=(tk%mod)*(f%mod);
    ans=(ans+ad)%mod;ans-=1;
    ans=ans+solve(f+1);
    ans%=mod;
    //cout<<ans<<endl;
    return ans;
}


int main()
{
    id[0]=1;for(int i=1;i<=62;i++)id[i]=id[i-1]*2;
    a[0]=1;a[1]=2;a[2]=6;
    for(int i=3;i<=62;i++){
        long long aa=id[i-2]%mod;
        aa=aa*((aa*2+1)%mod)%mod;
        a[i]=(a[i-1]+a[i-1])%mod;
        a[i]=(a[i]+aa-1)%mod;
        //if(a[i]<0)cout<<i<<endl;
    }
    int t;scanf("%d",&t);
    while(t--){
        long long c;scanf("%lld",&c);
        printf("%lld\n",solve(c));
    }
}

1008:RMQ Similar Sequence

思路:构造出a数组的笛卡尔树,然后就可以求得b数组的笛卡尔树与a同构的概率是\frac{1}{\prod_{i=1}^{n}siz[i]},也就是1除以每个位置的子树的大小。由于每个数是0到1随机的,所以期望是\frac{1}{2},那么总期望就是\frac{n}{2},所以答案就是\frac{n}{2\prod_{i=1}^{n}siz[i]}。其中,笛卡尔树的学习推荐一个链接:https://www.zybuluo.com/KirinBill/note/871204

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int mx=1e6+5;

struct node{
    int val,sz;
    int l,r,pre;
}t[mx];
stack<int>st;

void init(int n)
{
    for(int i=0;i<=n;i++)t[i].l=t[i].r=t[i].pre=t[i].sz=0;
    t[0].val=inf;
    while(!st.empty())st.pop();
    st.push(0);
}

void build(int n)
{
    for(int i=1;i<=n;i++){
        while(!st.empty() && t[st.top()].val<t[i].val)st.pop();
        int pre=st.top();
        t[i].pre=pre;t[i].l=t[pre].r;t[t[pre].r].pre=i;t[pre].r=i;
        st.push(i);
    }
}

void dfs(int u)
{
    if(u==0)return ;
    t[u].sz=1;
    dfs(t[u].l);
    dfs(t[u].r);
    t[u].sz+=t[t[u].l].sz+t[t[u].r].sz;
}

ll inv[mx];
void init()
{
    inv[1]=1;
    for(int i=2;i<mx;i++)inv[i]=inv[mod%i]*(mod-mod/i)%mod;
}

int main()
{
    int T;scanf("%d",&T);init();
    while(T--){
        int n;scanf("%d",&n);init(n);
        for(int i=1;i<=n;i++)scanf("%d",&t[i].val);
        build(n);dfs(t[0].r);
        ll ans=n*inv[2]%mod;
        for(int i=1;i<=n;i++)ans=ans*inv[t[i].sz]%mod;
        printf("%lld\n",ans);
    }
}

1009:Lyndon Substring

不会

1010:Turn Off The Light

不会

1011:Time Zone

思路:模拟。好像浮点数会有误差,所以不要用。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
int flag,h,m,is;
char s[20];

void get()
{
    if(s[3]=='+')flag=1;else flag=0;
    int len=strlen(s);int i;
    for(i=4;i<len;i++){
        if(s[i]=='.')break;
        else h=h*10+s[i]-'0';
    }
    if(i<len && s[i]=='.'){
        is=1;m=s[i+1]-'0';
    }
}

void print(int k)
{
    int st=60*24;
    if(k>=st)k-=st;
    else if(k<0)k+=st;
    if(k/60>=10)printf("%d",k/60);
    else printf("0%d",k/60);
    printf(":");
    if(k%60>=10)printf("%d\n",k%60);
    else printf("0%d\n",k%60);
}

int main()
{
    int t;scanf("%d",&t);
    while(t--){
        int a,b;scanf("%d%d",&a,&b);
        scanf("%s",&s);
        flag=-1,h=0,m=0,is=0;get();
        int x=a*60+b;
        if(flag==1){
            if(h>=8){
                int tmp=(h-8)*60+m*6;
                print(tmp+x);
            }
            else {
                int tmp=(8-h)*60-m*6;
                print(x-tmp);
            }
        }
        else{
            int tmp=8*60+h*60+m*6;
            print(x-tmp);
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值