130827组队赛Regionals 2012, North America - Greater NY

11 篇文章 0 订阅
3 篇文章 0 订阅

A.Hailstone HOTPO

这题意思是对n进行操作,当n为偶数时,n除以2,当n奇数时,n*3+1,直到n=1时结束。。。求这期间出现的最大值,很简单的题目。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
int main()
{
    int t,n,c,r;
    RD(t);
    while(t--)
    {
        RD(c);
        RD(r);
        n=r;
        while(n!=1)
        {
            if(n%2==1)
            {
                n*=3;
                n++;
            }
            else
            {
                n/=2;
            }
            r=max(r,n);
        }
        printf("%d %d\n",c,r);
    }
    return 0;
}

B.B-Casting

题意大体就是让你将一个B进制的数去模(B-1)得到的答案。简单的数制转化题,而且数的范围也不大,可以直接暴力,但oj就是不判题,所以就不贴代码了。


C.Pen Counts

这题就是将三只鸡放在三角形中,给你一个总距离,问你有多少种情况,其实就是给你三角形的周长,让你求三角形的数量。我们可以假设三角形边长为x,y,z,已知z,则有x+y=n-z,x-y<z,令x-y=t,(0<=t<z),求解得 x=(n-z+t)/2,y=(n-z-t)/2,对于y,ymax=(n-z)/2,ymin=(n-z-(z-1))/2。如果三边长不同,则+1。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
int main()
{
    int  T,t,k,p,i,high,low,r;
    RD(T);
    while(T--)
    {
        RD(k);
        RD(p);
        r=0;
        for(i=1; i<p; ++i)
        {
            low=max(i,(p-2*i)/2+1);
            high=(p-i)/2;
            if(low<=high)
            {
                t=0;
                if(3*i<=p&&4*i>p)
                {
                    t++;
                }
                if(3*i<p&&(p-i)%2==0)
                {
                    t++;
                }
                r+=(high-low+1)*2-t;
            }
        }
        printf("%d %d\n",k,r);
    }
    return 0;
}

D.Maximum Random Walk

这题题意还是挺难理解的,它要求的是走n步后,所有情况中最右边点的数学期望。

我定义了一个三维数组dp[2][2001][2001],2是滚动数组,保存的是走了i步,中间的2001是走到了j位置,最后的2001保存的是走到最右边的位置。分为刚好到达最右位置和不在最右位置两种情况。然后直接概率dp过程就行了。这是最暴力的过程了,最后一个样例干脆很慢才跑出来。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stdio.h>
#define N 1050
#define INF 99999999
using namespace std;
double dp[2][2003][2003];
int main()
{
    int i,j,l,k,n,t;
    double p,q,r,sum;
    RD(t);
    while(t--)
    {
        RD(k);
        RD(n);
        scanf("%lf%lf",&p,&q);
        r=1.0-p-q;
        memset(dp,0,sizeof(dp));
        dp[0][1001][1001]=1;
        for(i=1; i<=n; ++i)
        {
            for(j=1001-i; j<=1001+i; ++j)
            {
                for(l=max(1001,j);l<=1001+i; ++l)
                {
                    if(l==j)
                    {
                        dp[i%2][j][l]=dp[(i-1)%2][j][l]*r+dp[(i-1)%2][j-1][l]*q+dp[(i-1)%2][j-1][l-1]*q;
                    }
                    else
                    {
                        dp[i%2][j][l]=dp[(i-1)%2][j][l]*r+dp[(i-1)%2][j-1][l]*q+dp[(i-1)%2][j+1][l]*p;
                    }
                }
            }
        }
        sum=0;
        for(i=1001-n; i<=1001+n; ++i)
        {
            for(j=1001; j<=1001+n; ++j)
            {
                sum+=dp[n%2][i][j]*(j-1001);
            }
        }
        printf("%d %.4f\n",k,sum);
    }
    return 0;
}


E.Faulhaber's Triangle

一道模拟题,关键在于它给的式子,F(i,j)=i/j*F(i-1,j-1)。我选择用两个二维数组保存分子和分母,依次得到每个值,但由于有些是整数,有些是负数,所以需要GCD和判负数。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 1000000007
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
long long f[401][401],g[401][401];
long long gcd(long long a,long long b)
{
    if(a%b==0)
    {
        return b;
    }
    return gcd(b,a%b);
}
void ff()
{
    f[0][1]=1;
    f[1][1]=1;
    f[1][2]=1;
    g[0][1]=1;
    g[1][1]=2;
    g[1][2]=2;
    int i,j;
    long long l,r,ll,rr,m;
    for(i=2;i<=400;++i)
    {
        l=r=1;
        for(j=i+1;j>=2;--j)
        {
            ll=f[i-1][j-1]*i;
            rr=g[i-1][j-1]*j;
            m=gcd(ll,rr);
            f[i][j]=ll/m;
            g[i][j]=rr/m;
            m=gcd(r,g[i][j]);
            l=g[i][j]*l/m-f[i][j]*r/m;
            r=r*g[i][j]/m;
        }
        f[i][1]=l;
        g[i][1]=r;
        m=gcd(f[i][1],g[i][1]);
        f[i][1]/=m;
        g[i][1]/=m;
    }
}
int main()
{
    ff();
    int t,k,x,y;
    RD(t);
    double w;
    while(t--)
    {
        RD(k);
        RD(x);
        RD(y);
        printf("%d ",k);
        if(f[x][y]%g[x][y]==0)
        {
            printf("%lld\n",f[x][y]/g[x][y]);
        }
        else
        {
            w=double(f[x][y])/double(g[x][y]);
            if(w<0.0&&f[x][y]>0)
            {
                printf("%lld/%lld\n",-f[x][y],-g[x][y]);
            }
            else
            {
                printf("%lld/%lld\n",f[x][y],g[x][y]);
            }
        }
    }
    return 0;
}

F.The King's Ups and Downs

一道组合数学和dp结合的题目,在每个人进入队伍时,他都有两种情况:

1.到队伍两边:到队伍两边比较简单,就直接乘2就行了;

2.到队伍中间:我们可以假设有j个人在他的左边,有i-j-1个人在他的右边。这样的话就是dp[j]*dp[i-j-1]。而i-1个人中取出j个就是组合公式C(i-1,j)。因为只求了一半,所以需要乘2。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
long long f[22];
long long p(int a)
{
    int i;
    long long s=1;
    for(i=1; i<=a; ++i)
    {
        s=s*i;
    }
    return s;
}
long long Cn(int x,int y)
{
    return p(x)/p(y)/p(x-y);
}
void g()
{
    int i,j;
    f[1]=1;
    f[2]=2;
    f[3]=4;
    for(i=4; i<=20; ++i)
    {
        f[i]+=f[i-1];
        for(j=1; j<i-1; ++j)
        {
            if(j==1||(i-j)==2)
            {
                f[i]+=(f[j]*f[i-j-1]/2)*Cn(i-1,j);
            }
            else
            {
                f[i]+=(f[j]*f[i-j-1]/4)*Cn(i-1,j);
            }
        }
    }
}
int main()
{
    int t,n,k;
    g();
    RD(t);
    while(t--)
    {
        RD(k);
        RD(n);
        printf("%d %lld\n",k,f[n]);
    }
    return 0;
}

H.Windmill Animation

一道计算几何题,看懂题意就很好做了。题意如下:给m个点,给一条与x轴夹角为angle的直线,直线从给定的l点穿过,直线开始以给定的l点逆时针旋转,当直线每次最初碰到一个点时,旋转轴点换成这个点,继续旋转。输出直线依次碰到的s个点。

想法:以转轴点向上和向下分别得到两条射线pa、pb,直线左边的点与射线pa比较得到夹角,直线右边的点与射线pb比较得到夹角。夹角最小的点就是下一个转轴点,然后更新射线。依次往下旋转,输出s次答案。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
#define pi 3.1415926535
#define INF 1e10
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
struct xl
{
    double x,y;
    int id;
}p[22];
double dot(xl a,xl b)//点积
{
    return a.x*b.x+a.y*b.y;
}
double det(xl a,xl b)//叉积
{
    return a.x*b.y-a.y*b.x;
}
double dis(xl a)//射线长度
{
    return sqrt(a.x*a.x+a.y*a.y);
}
int main()
{
    int T,k,m,s,l,i,j,ll,f,flag;
    double ag,dr,ds,da,MAX;
    xl pa,pb,px;
    RD(T);
    while(T--)
    {
        RD(k);
        RD(m);
        RD(s);
        RD(l);
        scanf("%lf",&ag);
        for(i=1;i<=m;++i)
        {
            RD(p[i].id);
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        ll=l;
        ag=ag*pi/180.0;
        pa.x=cos(ag);
        pa.y=sin(ag);
        pb.x=-pa.x;
        pb.y=-pa.y;
        printf("%d",k);
        FOR(1,s,i)
        {
            MAX=-INF;
            FOR(1,m,j)
            {
                if(j==l||j==ll)
                {
                    continue;
                }
                px.x=p[j].x-p[l].x;
                px.y=p[j].y-p[l].y;
                dr=det(pa,px);//判断上下
                if(dr>0)
                {
                    da=dot(pa,px)/dis(px)/dis(pa);//求角度cos值
                    if(da>MAX)
                    {
                        MAX=da;
                        flag=j;
                        f=1;
                    }
                }
                else if(dr<0)
                {
                    da=dot(pb,px)/dis(px)/dis(pb);
                    if(da>MAX)
                    {
                        MAX=da;
                        flag=j;
                        f=-1;
                    }
                }
            }
            printf(" %d",flag);
            ll=l;
            l=flag;
            if(f==1)
            {
                pb.x=p[ll].x-p[l].x;
                pb.y=p[ll].y-p[l].y;
                pa.x=-pb.x;
                pa.y=-pb.y;
            }
            else
            {
                pa.x=p[ll].x-p[l].x;
                pa.y=p[ll].y-p[l].y;
                pb.x=-pa.x;
                pb.y=-pa.y;
            }
        }
        printf("\n");
    }
    return 0;
}

J.Mystery

这题的要求就是累加确定位置,输出相应的位置的字符就行。注意输入输出。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 100000
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
int T,n,i,j,id,ca,len;
char s[5555];
int main()
{
    RD(T);
    while(T--)
    {
        cin>>ca;
        cout<<ca<<" ";
        gets(s);
        gets(s);
        len=strlen(s);
        RD(n);
        id=0;
        for(i=0; i<n; i++)
        {
            cin>>j;
            id+=j;
            id=(id%len);
            if(id<0)
            {
                id+=len;
            }
            cout<<s[id];
        }
        printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:这段引用是一段C++代码,用于处理一个01序列的查询。代码中使用了前缀和和后缀和的思想,通过计算每个位置之前1的个数和之后1的个数,来处理查询区间内的操作。具体的实现细节可以参考代码注释。\[1\] 引用\[2\]:在处理多组询问时,为了不改变非连续1的计数,代码将区间分成两段处理。左半段都是1的情况单独处理,后半段第一个位置为0,可以通过前缀和相减来计算。这样可以保证在处理查询时不会影响到非连续1的计数。\[2\] 引用\[3\]:这段引用是对一个二进制循环序列的定义和问题描述。一个好的二进制循环序列是指通过一系列操作可以使其变为空序列。而一个二进制循环序列的美丽度被定义为使其变为好序列所需的最小修改次数。每次修改可以翻转序列中的任意一个元素,即0变为1,1变为0。给定一个长度为n的二进制字符串a和q个查询,每个查询给出两个整数li和ri,需要回答f(aliria\[li..ri\]),其中我们将子字符串aliria\[li..ri\]视为一个循环序列。\[3\] 问题: 请问这段代码的作用是什么? 回答: 这段代码的作用是处理一个01序列的查询。通过计算每个位置之前1的个数和之后1的个数,来处理查询区间内的操作。在处理多组询问时,为了不改变非连续1的计数,代码将区间分成两段处理,保证在处理查询时不会影响到非连续1的计数。最终输出每个查询区间的结果。\[1\]\[2\] #### 引用[.reference_title] - *1* *2* [ICPC22网络(1) - A 01 Sequence(前缀和,思维)](https://blog.csdn.net/Mr_dimple/article/details/126983251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [The 2022 ICPC Asia Regionals Online Contest - A 01 Sequence](https://blog.csdn.net/qq_35339563/article/details/126959132)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值