• SCAU Individual Contest #1


    总结一下就是自己太弱。每次打比赛遇到比较难题就喜欢瞎开题,结果都是每题想一下,然后就是结束了。

    A:题意让你用小写字母构造一个总共有K个的回文串,比如aba的话就是{a}{b}{a}{aba}四个,比较水,直接a-z一直循环够K个字母就行了,因为这样回文串只能是每个字符自己本身,比赛脑残写成大写WA了一发.题目:https://www.codechef.com/problems/NDIFFPAL

    B:题目大意就是给你N个格子,每次必须填连续三个格子而且填相同的数,格子上如果填过数字的话,再填是直接覆盖,给你一个序列,问你能否把格子填成这种形式,输出Yes或者No。解法就是直接扫一次,如果序列里有三个连续相同的数字的话就Y,因为涂的时候我们可以把这三个留在最后填,然后其他就相当于可以一个个填。也是比较水。题目:https://www.codechef.com/problems/MAKEART

    下面几题就是开始待机模式了= =

    C:题意让你构造一个序列,序列必须是1-x的全排列之一,而且x不能超过100,这个序列还必须有K个最长上升子序列。题目:https://www.codechef.com/problems/MAKELIS

    解法真是奥秘重重。。做题质量不够,数量也不够,认识的套路少,太弱。

    假如K小于等于100,就可以直接倒序输出。然而没什么卵用啊,题目的K是10^5,然后正确套路就是分解K成其他进制。

    官方题解就是差不多这样说吧。。不过看不太懂,因为上面出现一大波乱码。看了下没乱码的公式,YY了下。大概就是这样

    [……]表示这个序列的一部分

    假如K=6的话,把K分解成二进制就是110(2)=0+2*(1+2),从最里面那个开始看起0+2*(1+[2,1])->0+2*([1]+[2,1])=0+2*([3,2,1])=0+[2,1]*([3,2,1])=[3,2,1,5,4]

    乘上二的话,就是在最后面加上两个连续倒序的数。相加的话就是在最前面加上一个数

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <stack>
    typedef long long ll;
    #define X first
    #define Y second
    #define mp(a,b) make_pair(a,b)
    #define pb push_back
    #define sd(x) scanf("%d",&(x))
    #define Pi acos(-1.0)
    #define sf(x) scanf("%lf",&(x))
    #define ss(x) scanf("%s",(x))
    #define maxn 10000000
    #include <ctime>
    const int inf=0x3f3f3f3f;
    const long long mod=1000000007;
    using namespace std;
    vector<int> turn(int k)
    {
        vector<int>a;
        while(k)
        {
            a.pb(k%2);
            k/=2;
        }
        return a;
    }
    int main()
    {
        #ifdef local
        freopen("in","r",stdin);
        //freopen("data.txt","w",stdout);
        int _time=clock();
        #endif
        int t;
        cin>>t;
        while(t--)
        {
            int k;
            sd(k);
            if(k==1)
            {
                printf("1
    1
    ");
                continue;
            }
                vector<int>bit,a,b;
                bit=turn(k);
                int len=bit.size();
                int cnt=1;
                int head;
                for(int i=len-1;i>=0;i--)
                {
                    if(bit[i]==1)
                    {
                        head=len-i-1;
                        while(b.size()!=head)
                            b.pb(cnt++);
                    }
                    if(i)
                    {
                        a.pb(cnt+1);
                        a.pb(cnt);
                        cnt+=2;
                    }
                }
                printf("%d
    ",a.size()+b.size());
                for(int i=0;i<b.size();i++)
                    printf("%d ",b[i]);
                for(int i=0;i<a.size();i++)
                    printf("%d ",a[i]);
                putchar('
    ');
        }
        #ifdef local
        printf("time: %d
    ",int(clock()-_time));
        #endif
    }
    View Code

     D:给你n个数a1,a2……,an,增长m次,增长规律就是每两个数直接会生成新的数,数的值等于那两个数的和.再给你m,还有x,y问你m次之后,[x,y]区间里面的和是多少。题目:https://www.codechef.com/problems/CHSPARR

    官方题解老是乱码。。自己手算好久,推出一个规律...

    {1,6,9}->{1,7,6,15,9}

    假设sum[m][i]是第m次后的前i项和,a[m][i]是第m次后的第i个元素,m=1,i是奇数的时候,如i=3,我们会发现1+7+6+15=2*(1+6)+(1+6+9-1),发现了吗。奇数位是上一个序列生成的数。。

    i&1==1的时候,sum[m][i]=sum[m-1][i/2]*2+sum[m-1][i/2+1]-a[0];

    为什么呢,因为sum[m-1][i/2]*2等于[0,i/2]这个区间生成的数+a[0]+a[m-1][i/2],再加上sum[m-1][i/2+1]等于a[m-1][0,i/2]+a[i][i/2+1];

    a[m-1][i/2]+a[m-1][i/2+1]等于?,就等于a[m][i]。所以上面的式子成立。

    上面是奇数的情况,偶数也差不多这样推。。所以我们可以记忆化递推就可以了

    奇数推导(xjb猜)

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    #define X first
    #define Y second
    #define mp(a,b) make_pair(a,b)
    #define pb push_back
    #define sd(x) scanf("%d",&(x))
    #define Pi acos(-1.0)
    #define sf(x) scanf("%lf",&(x))
    #define ss(x) scanf("%s",(x))
    #define maxn 50005
    const int inf=0x3f3f3f3f;
    const ll mod=1000000007;
    ll a[100005];
    map<ll,ll>book[35];
    ll solve(int m,ll x)
    {
        if(x==0)return a[0];
        if(m==0)return a[x];
        if(book[m].count(x))return book[m][x];
        if(x&1)return book[m][x]=(solve(m-1,x/2+1)%mod+2*solve(m-1,x/2)%mod-a[0]+mod)%mod;
        else return book[m][x]=(2*solve(m-1,x/2)%mod+solve(m-1,x/2-1)%mod-a[0]+mod)%mod;
    }
    int main()
    {
    #ifdef local
        freopen("in","r",stdin);
        //freopen("out","w",stdout);
        int _time=clock();
    #endif
        int t;
        sd(t);
        while(t--)
        {
            int n,m;
            ll x,y;
            cin>>n>>m>>x>>y;
            x--,y--;
            for(int i=0;i<n;i++)
            {
                scanf("%lld",&a[i]);
                a[i]+=(i?a[i-1]:0);
            }
            for(int i=1;i<=m;i++)book[i].clear();
            cout<<(solve(m,y)-(x?solve(m,x-1):0)+mod)%mod<<endl;
        }
    #ifdef local
        printf("time: %d
    ",int(clock()-_time));
    #endif
    }
    View Code

    未完

  • 相关阅读:
    操作正则表达式的公共类
    验证码类
    强制转化常用函数
    实现Base64编码与其它编码转换的类
    关于任务管理器踩过的坑,程序员必看!
    每次找Internet选项感到抓狂?一键打开!
    教你避过安装TensorFlow的两个坑
    HTML中id与name的通俗区别
    VS code代码对齐快捷键
    form和table的区别
  • 原文地址:https://www.cnblogs.com/scau-zk/p/5657700.html
Copyright © 2020-2023  润新知