2021ccpc网络赛选拔赛补题

这次网络赛真是一言难尽,hdoj不说,自己也是大脑空白,再加上眼睛巨难受,划水五小时,被队友带躺。

1002 Time-division Multiplexing

题目思路

赛中有演员告诉我1到12的gcd是4e8,我直接懵逼,不知道咋搞。。。幸好另一个队友过了。

思路其实就是暴力,n个串每个串长度不大于12,那么我们暴力模拟出结合后的串的循环节就好了。
这个循环节的长度其实就是所有串长度的lcm乘上串的个数。1到12的gcd是27720,所以循环节长度最大到n*27720。我们暴力模拟出串的长度后,用双指针求解就好。还要注意我们需要取两段循环节才能保证答案正确(因为这个地方wa了好久)。。

ac代码

const int maxn = 6e6+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
const double pi = acos(-1);

char str[maxn];
char a[200][20];
int len[200];
int mp[100];
int cnt;

int gcd(int x,int y)
{
    return y==0?x:gcd(y,x%y);
}

int main()
{

    int _;
    scanf("%d",&_);
    while(_--)
    {
        int n;
        scanf("%d",&n);
        cnt=0;
        ms(mp,0);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",a[i]);
            len[i]=strlen(a[i]);
            for(int j=0;j<len[i];j++)
            {
                if(!mp[a[i][j]-'a'])
                    mp[a[i][j]-'a']++,cnt++;
            }

        }
        int lcm=1;
        for (int i = 1; i <=n; i++) {
            lcm = (lcm * len[i])  / gcd(lcm, len[i]);
        }
        for(int i=1;i<=n;i++)
        {
            int now=i;
            for(int j=1;j<=lcm;j++)
            {
                str[now-1]=a[i][(j-1)%len[i]];
                now+=n;
            }
        }

        int N=n*lcm;
        for(int i=0;i<N;i++)
        {
            str[i+N]=str[i];
        }
        N*=2;
        int l=0;
        ms(mp,0);
        int sum=0;
        int ans=1e9;
        for(int r=0;r<N;r++)
        {
            mp[str[r]-'a']++;
            if(mp[str[r]-'a']==1)
            {
                sum++;
            }
            while(sum==cnt&&l<=r)
            {
                if(ans>r-l+1)
                {
                    ans=r-l+1;
                }
                mp[str[l]-'a']--;
                if(mp[str[l]-'a']==0)
                {
                    sum--;
                }
                l++;
            }

        }

        printf("%d\n",ans);
    }
}

1006 Power Sum

题目思路

经机房大佬描述:我们观察可以发现任意四个连续的数通过1001的方式加减后都可以得到4(可以自己手算下)。那么我们只需要对n模4,根据余数构造开始的式子,再加上多个1001就行了。

这题赛后自己写了一直t,然后交了机房几个赛中ac的代码赛后也t了。。。就不放代码了。。

1007 Function

题目思路

简单观察后,可以将f(x)的式子变化成这样
  f ( x ) = ( A g ( x ) + B ) x 2 + ( C g 2 ( x ) + D g ( x ) ) x   . \ f(x)= (Ag(x)+B)x^2+(Cg^2(x)+Dg(x))x \,.  f(x)=(Ag(x)+B)x2+(Cg2(x)+Dg(x))x.
对于这个式子,ABCD都是已知的,如果我们确定下g(x)的值,我们就能够的到一个关于x的二次函数。
根据g(x)的定义,我们发现它最大只到54,并且x最大是1e6。
所以我们可以预处理出所有g(x)对应的x值,然后我们枚举g(x)的值,三分求最小值。

作为一个蒟蒻,二分本来写的也不多,三分就更少了,赛中写了好久都没写明白,哭死。。。
发现赛中写的一份代码wa的原因是三分板子出了问题。。。。麻了

ac代码

const int maxn = 1e6+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
const double pi = acos(-1);


ll n,a,b,c,d;
vector<int>vec[100];

int work(int x)
{
    int tem=0;
    while(x)
    {
        tem+=x%10;
        x/=10;
    }
    return tem;
}

ll calc(ll x,ll a,ll b)
{
    return a*x*x+b*x;
}

int main()
{

    for(int i=1;i<=maxn;i++)
    {
        vec[work(i)].push_back(i);
    }
    int _;
    scanf("%d",&_);
    while(_--)
    {
        scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&n);
        ll ans=llinf;
        for(int i=1;i<=54;i++)
        {
            if(vec[i].size()==0)continue;
            ll A=(a*i+b);
            ll B=(c*i*i+d*i);
            int l = 0;
            int r = upper_bound(vec[i].begin(), vec[i].end(), n) - vec[i].begin();
            if(r==0)continue;
            r--;
            if(A<=0)
            {
                ans=min(ans,calc(1LL*vec[i][0],A,B));
                ans=min(ans,calc(1LL*vec[i][r],A,B));

            }else
            {
                ll ansL=llinf,ansR=llinf;
                while (l<=r)
                {
                    int lmid = l + (r - l) / 3;
                    int rmid = r - (r - l) / 3;
                    ansL = calc(vec[i][lmid],A,B),ansR = calc(vec[i][rmid],A,B);
                    if(ansL <= ansR)
                        r = rmid - 1;
                    else
                        l = lmid + 1;



                }
                ans=min(ans,min(ansL,ansR));
            }
        }
        printf("%lld\n",ans);
    }
}

1011 Shooting Bricks

洛谷原题链接

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值