2018 Multi-University Training Contest 1

hdu 6298 Maximum Multiple

题目要求把n拆成3个数,且都是n的因子切求和为n 其要求输出的3个数的乘积最大

那么就要把这3个数尽量靠近,1:1:1为最好,但如果不能拆成这样的话,就要想到1:1:2这种情况,

因为111的情况下,1+1+1=3且1|3,112的情况下 1+1+2=4且1|4,2|4 

所以122是不行的,因为1+2+2=5,但是2不能整除5所以只有n能整除3或者4才能输出答案。然后按比例求个乘积即可。

#include<bits/stdc++.h>
using namespace std;
int main(){
    
    long long n;
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%lld",&n);
        if(n%3!=0&&n%4!=0)
        cout<<"-1"<<endl;
        else  if(n%3==0)
        {
          long long a=n/3;
          long long ans=a*a*a;
          printf("%lld\n",ans);
        }
        else if(n%4==0)
        {
            long long a=n/2;
            long long b=n/4;
            long long ans=a*b*b;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

 

hdu 6300 Triangle Partition

给3n个点,求能组成n个三角形的组合方式且每2个三角形之间没有重合(包括点)

那么我们只要将点按照x坐标从左到右排序,然后一次每行输出3个点的id即可

#include<bits/stdc++.h>
using namespace std;
struct node{
    long long a,b;
    int id;
}p[99999];
bool cp(node x,node y)
{
    if(x.a!=y.a)return x.a<y.a;
    return x.b<y.b;
}
int main(){
    
    long long n;
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%lld",&n);
        for(int i=1;i<=n*3;i++)
        scanf("%lld%lld",&p[i].a,&p[i].b),p[i].id=i;
        sort(p+1,p+1+3*n,cp);
        for(int i=1;i<=n*3;i+=3)
        printf("%d %d %d\n",p[i].id,p[i+1].id,p[i+2].id);
        
    }
    return 0;
}

 

 

hdu 6038 Time Zone

模拟 ,注意下输入的东西即可

#include<bits/stdc++.h>
using namespace std;
#define LL long long int
int T;
int x,y;
char op[11];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d UTC%s",&x,&y,&op);
        int opp=0;
        int oppp=0;
        int flag;
        if(op[0]=='-') flag=-1;
        else flag=1;
        for(int i=1;op[i];i++)
        {
            if(op[i]>='0'&&op[i]<='9')
                opp=opp*10+op[i]-'0';
            if(op[i]=='.')
            {
                oppp=op[i+1]-'0';
                break;
            }
        }
        opp=opp*60+oppp*6;
        opp*=flag;
        opp-=480;
        y+=opp;
        while(y<0)
        {
            y+=60;x--;
        }
        while(y>59)
        {
            y-=60;x++;
        }
        y=(y+600)%60;
        x=(x+240)%24;
        printf("%02d:%02d\n",x,y);
    }
    return 0;
}

 

hdu 6301 Distinct Values

 

首先按照左端排序,然后长区间放前面。

暴力会超时,优化方法就利用集合来快速找到需要放进去的数字。

用优先队列也可以

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,t,ans[100006];
struct node
{
    int l,r,id;
    friend bool operator <(node a,node b)
    {
        return a.l==b.l?a.r>b.r:a.l<b.l;
    }
}q[100006];
set<int>s;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        s.clear();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            s.insert(i);
        for(int i=1;i<=m;i++)
            scanf("%d%d", &q[i].l, &q[i].r);
        sort(q+1, q+m+1);
        int r=0,l=1;
        for(int i=1;i<=m;i++)
        {
            if(q[i].r <= r)
                continue;
            if(q[i].l > r)
            {
                while(r<q[i].l)
                    ans[++r]=1;
                while(l<q[i].l) s.insert(ans[l++]);
                if((*s.begin())==1) s.erase(s.begin());
                while(r<q[i].r)
                {
                    ans[++r]=(*s.begin());
                    s.erase(s.begin());
                }
            }
            else if(q[i].l<=r)
            {
                while(l<q[i].l) s.insert(ans[l++]);
                while(r<q[i].r)
                {
                    ans[++r]=(*s.begin());
                    s.erase(s.begin());
                }
            }
        }
        while(r<n)
            ans[++r]=1;
        for(int i=1;i<=n;i++)
            {
            	if(i>1)cout<<" ";
            	cout<<ans[i];
			}
			cout<<endl;
    }
    return 0;
}

 

 

hdu 6299 Balanced Sequence

 

给出n个小括号串,让你将它们头尾拼起来,然后处理括号匹配问题求括号匹配的最大长度。

首先我们对于输入进来的每一个字符串,都可以直接算得它本身的括号匹配的长度。

然后它就会剩下 a个右括号和b个左括号的组合。类似于))))))(((((((((这样的情况,只不过a和b不一定相同。

那么问题就变成去拼这些东西求括号匹配最大长度。

我们肯定让 )))((((((((((((((((这种左括号大于右括号的尽量在左边,让)))))))))))))))))))(((这样的尽量在右边

那如果都是))))))))))))))))))))))))((这样的 那么我们就让(越少的放在最后面,

如果都是))(((((((((((((((((((这样的,我们就让)越少的放在最前面 ,那么最后会是 )))...............(((这样的情况就是最优的

 

#include<bits/stdc++.h>
using namespace std;
struct node{
    int l,r;
}p[111111];
char s[111111];
bool cp(const node &x,const node &y)
{
    if(x.l>x.r&&y.l<=y.r)
    return 1;
    if(x.r>=x.l&&y.r<y.l)
    return 0;
    if(x.r>=x.l&&y.r>=y.l)
    return x.l>y.l;
    return x.r<y.r;
}
int main()
{
    int t;
    scanf("%d",&t);
    
    while(t--)
    {
       int n;
       scanf("%d",&n);
       int ans=0;
       for(int j=0;j<n;j++)
       {
           scanf("%s",s);
           int l=strlen(s);
        int jl=0;
        int jr=0;
           for(int i=0;i<l;i++)
           {
               if(s[i]=='(')
               jl++;
               if(s[i]==')')
               {
                   if(jl>0)
                   {
                       jl--;
                       ans+=1;
                   }
                   else {
                       jr++;
                   }
               }
           }
           p[j].l=jl;
            p[j].r=jr;
       }
       sort(p,p+n,cp);
       int le=0;
       int ri=0;
       for(int i=0;i<n;i++)
       {
             if(p[i].r>=le)
             {
                 p[i].r-=le;
                 ans+=le;
                 le=0;
                 ri+=p[i].r;
                 le+=p[i].l;
          }
          else{
              ans+=p[i].r;
              le-=p[i].r;
              le+=p[i].l;
          }
       }
       printf("%d\n",ans*2);
    }
    return 0;
}

 

hdu  6304  Chiaki Sequence Revisited

规律

学习一下builtin 。。。。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+10;
const ll mod=1e9+7;
ll num[100],p[100];
void init(){
    num[0]=p[0]=1;
    for (int i=1;i<=63;i++){
        num[i]=2*num[i-1]+1;
        p[i]=p[i-1]*2;
    }
}
ll n;
ll inv2=(mod+1)/2;
ll getsum(ll pos){
    ll sum=0;
    for (ll i=1;i<=pos;i*=2){
        ll num=(pos-i)/(2*i);
        ll Max=i+num*(2*i);
        num=(num+1)%mod;
        Max=(Max+i)%mod;
        Max=Max*num%mod;
        Max=Max*inv2%mod;
        Max=Max*(__builtin_ctz(i)+1)%mod;
        sum=(sum+Max)%mod;
    }
    return (sum+1)%mod;
}
int main(){
    int t;
    scanf("%d",&t);
    init();
    while (t--){
        scanf("%lld",&n);
        ll pos=0;
        n--;
        if (n==0){
            printf("1\n");
            continue;
        }
        ll temp=n;
        for (int i=62;i>=0;i--){
            if (temp>=num[i]){
                temp-=num[i];
                pos+=p[i];
            }
        }
        //cout<<"pos="<<pos<<endl;
        ll sum1=getsum(pos);
        if (temp){
            sum1=(sum1+temp%mod*(pos+1)%mod)%mod;
        }
        printf("%lld\n",sum1);
    }
 
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值