2018 Multi-University Training Contest 1

 http://acm.hdu.edu.cn/search.php?field=problem&key=2018+Multi-University+Training+Contest+1&source=1&searchmode=source

Maximum Multiple

n=x+y+z,x|n,y|n,z|n;

n=t1*x,n=t2*y,n=t3*z;

1/t1+1/t2+1/t3=1;

假设t1>=t2>=t3;

解的:有三组解 1、2,4,4; 2、3,3,3;3、 2,3,6;

因为要求x*y*z的最大值,所以第三组解明显比第二组解小,所以第三个答案舍弃

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
const int maxn=1e6+7;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        long long m;
        if(n%3==0)
        {
            m=(long long)n/3*(long long)n/3*(long long)n/3;
            printf("%lld\n",m);
        }
        else if(n%4==0)
        {
            m=(long long)n/2*(long long)n/4*(long long)n/4;
            printf("%lld\n",m);
        }
        else
        {
            printf("-1\n");
        }
    }
}

Balanced Sequence

给你n个括号的字符串,这n个字符串连接以后最多有多少个匹配的半括号,匹配的括号可以不连续

例如:)()(()( 结果为4

可以先将每个字符串中的已经匹配好的括号挑出来,所有的字符串都变成"))))",")))(((","(((",这三种形式

两个字符串排序a,b; (a排在b前面)x=min(a.l,b.r),(b排在a前面)y=min(a.r,b.l);可以匹配的括号数量,如果x>y

则a放在前面,若x<y则b放前面,若x=y,则右边括号少的放前面

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string>
#include<string.h>
#include<stack>
using namespace std;
const int maxn=1e5+7;
char str[maxn];
struct node
{
    int l,r;
} s[maxn];
bool cmp(node a,node b)
{
    int aa=min(a.l,b.r);
    int bb=min(a.r,b.l);
    if(aa==bb)
        return a.l>b.l;
    return aa>bb;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int ans=0;
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%s",str);
            s[i].l=s[i].r=0;
            for(int j=0; str[j]!='\0'; j++)
            {
                if(str[j]=='(')
                    s[i].l++;
                else
                {
                    if(s[i].l)
                    {
                        s[i].l--;
                        ans+=2;
                    }
                    else
                        s[i].r++;
                }
            }
        }
        sort(s,s+n,cmp);
        int l=0,r=0;
        for(int i=0; i<n; i++)
        {
            if(s[i].r>l)
            {
                ans+=2*l;
                l=0;
            }
            else
            {
                ans+=s[i].r*2;
                l-=s[i].r;
            }
            l+=s[i].l;
        }
        printf("%d\n",ans);
    }
}

 Triangle Partition

总共有3n个点,输出n行(a,b,c);a,b,c为可以构成三角形的点的编号,这n个三角形不相交(输出一种结果即可)

按照x轴排个序,如果x轴相同,按y轴排个序,按顺序输出即可

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string>
#include<string.h>
#include<stack>
using namespace std;
const int maxn=1e5+7;
struct node
{
    int x,y,id;
}p[3003];
bool cmp(node a,node b)
{
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=3*n;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            p[i].id=i;
        }
        sort(p+1,p+3*n+1,cmp);
        for(int i=1;i<=3*n;i++)
        {
            if(i%3)printf("%d ",p[i].id);
            else printf("%d\n",p[i].id);
        }
    }
}

Chiaki Sequence Revisited

\sum_{i=1}^{n}ai;

先打表:a[1]=1,a[2]=1,a[n]=a[n-a[n-1]]+a[n-1-a[n-2]];

1 1 2 2 3 4 4 4 5 6 6 7 8 8 8 8 9 10 10 11 12 12 12 13 14 14 15 16 16 16
16 16 17 18 18 19 20 20 20 21 22 22 23 24 24 24 24 25 26 26 27 28 28 28 29 30 30 31 32 32
32 32 32 32 33 34 34 35 36 36 36 37 38 38 39 40 40 40 40 41 42 42 43 44 44 44 45 46 46 47
48 48 48 48 48 49 50 50 51 52 52 52 53 54 54 55 56 56 56 56 57 58 58 59 60 60 60 61 62 62
63 64 64 64 64 64 64 64 65 66 66 67 68 68 68 69 70 70 71 72 72 72 72 73 74 74 75 

每个数字出现的次数

2 2 1 3 1 2 1 4 1 2 1 3 1 2 1 5 1 2 1 3 1 2 1 4 1 2 1 3 1 2
1 6 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 5 1 2 1 3 1 2 1 4 1 2 1 3
1 2 1 7 1 2 1 3 1 2 1 4 1 2 1

除去第一项,可以发现数字出现次数的规律为

前2^i项数字出现的次数和等于前2^(i-1)项数字出现的次数和*2+1;

还可以发现

1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37…………

2 6 10 14 18 22 26 30 34 …………

4 12 20…………

…………

为首项2^i,公差为2^(i+1)次方的等差数列

计算出数组a a[i]表示前2^i次方项数字出现次数的和  a[i]=2*a[i-1]+1;

求前n项的an的和,先求出第n项在数字出现次数数列里的位置

因为是从规律是从第二项开始n--;

计算出完整前n项在数字出现次数的值sum,剩余的项数的数量为tmp,对应的值为sum+1

 for(int i=62; i>=0; i--)
    {
        if(tmp>=a[i])
        {
            tmp-=a[i];
            sum+=f[i];
        }
    }

求出完整的对应的结果,最后结果加上第一项,求等差数列的和时除以2用逆元,否则会爆掉

int getnum(ll x)///出现的次数
{
    return lower_bound(f,f+63,x)-f+1;
}
ll solve(ll x)
{
    ll ans=0;
    for(ll i=1; i<=x; i=2*i)
    {
        ll num=(x-i)/(2*i);///公差
        ll an=i+num*(2*i);///末项
        num=(num+1)%mod;///项数
        ll res=(((i+an)%mod*num)%mod*inv)%mod;///等差数列和
        ans=(ans+res*getnum(i)%mod)%mod;
    }
    return (ans+1)%mod;
}

 

 

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string>
#include<string.h>
#include<stack>
#include<queue>
typedef long long ll;
using namespace std;
ll a[105],f[105];
const ll mod=1e9+7;
const ll inv=(mod+1)/2;
void init()
{
    a[0]=f[0]=1;
    for(int i=1; i<=62; i++)
    {
        f[i]=2*f[i-1];
        a[i]=2*a[i-1]+1;
    }
}
int getnum(ll x)
{
    return lower_bound(f,f+63,x)-f+1;
}
ll solve(ll x)
{
    ll ans=0;
    for(ll i=1; i<=x; i=2*i)
    {
        ll num=(x-i)/(2*i);
        ll an=i+num*(2*i);
        num=(num+1)%mod;
        ll res=(((i+an)%mod*num)%mod*inv)%mod;
        ans=(ans+res*getnum(i)%mod)%mod;
    }
    return (ans+1)%mod;
}
int main()
{
    int t;
    scanf("%d",&t);
    init();
    while(t--)
    {
        ll n;
        scanf("%lld",&n);
        if(n==1)
            printf("%lld\n",n);
        else
        {
            n--;
            ll sum=0,tmp=n;
            for(int i=62; i>=0; i--)
            {
                if(tmp>=a[i])
                {
                    tmp-=a[i];
                    sum+=f[i];
                }
            }
            ll ans=solve(sum);
            if(tmp)
            {
                ans=(ans+tmp*(sum+1))%mod;
            }
            printf("%lld\n",ans);
        }
    }
}

Time Zone

给你UTF+8的时间,求UTFx.y(x)的时间(-14<=x,x.y<=14,0<=y<=9)

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string>
#include<string.h>
#include<stack>
#include<queue>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int a,b;
        char s[10];
        scanf("%d %d %s",&a,&b,s);
        int len=strlen(s);
        int f=0;
        int num1=0,num2=0;
        a=((a+24)-8)%24;
        for(int i=0;i<len;i++)
        {
            if(s[i]=='.')
                f=i;
        }
        if(f)
        {
            if(f==6)
                num1+=((s[4]-'0')*10+(s[5]-'0')),num2+=(s[7]-'0')*6;
            else
                num1+=(s[4]-'0'),num2+=(s[6]-'0')*6;
        }
        else
        {
            if(len==6)
                num1+=((s[4]-'0')*10+(s[5]-'0'));
            else
                num1+=(s[4]-'0');
        }
        if(s[3]=='+')
        {

            b+=num2;
            a+=b/60;
            b=b%60;
            a=(a+num1)%24;
        }
        else
        {
            a--;
            a=(a+24)%24;
            b=b+60-num2;
            a+=b/60;
            b=b%60;
            a=((a+24)-num1)%24;
        }
        printf("%02d:%02d\n",a,b);
    }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值