noip前考试总结

为了让noip不翻车,在这里总结一下noip前的考试

因为学习时间有些少,所以可能更新较慢

August 31st

250pts

rank3/15

T1.传纸条

给定一个字符串,判断存在两个子串相等时候,子串的长度最长为多少,长度<=100

很简单,可以map暴力过

#include <cstdio>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>

using namespace std;

char a[1200003];
int n;
map<string, int> f;

bool pd(int x)//判断是否不存在长度为x的 
{
    f.clear();
    string str;
    for (int i = 0; i < x; i++)
        str.push_back(a[i]);
    for (int i = x; i <= n; i++)
    {
        f[str]++;
        if(f[str] >= 2)
            return false;
        if(i == n)
            return true;
        string str2 = str.substr(1);
        str2.push_back(a[i]);
        str = str2;
    }
    return true;
}

int main()
{
    freopen("message.in", "r", stdin);
    freopen("message.out", "w", stdout);
    scanf("%s", a);
    n = strlen(a);
    int l = 1, r = n;
    while(l < r)
    {
        int mid = (l + r) / 2;
        if(pd(mid))
            r = mid;
        else
            l = mid + 1;
    }
    printf("%d\n", l - 1);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2.合并序列

给定一堆序列数量k<=100,每个长度<=20万,现在让你合并,要求新序列中包含原序列的所有元素,且每个序列中元素相对位置不变,且合并后序列满足元素递减的元素位置数最小。

一开始我看错题了看TMD成逆序对了然后...各种暴力

然后我恍然大悟,但是思维改不过来了,写了一个贪心,每次在各个子序列头部找\(\ge\)当前合并后序列尾部的数且最小的数扔进来,如果没有就直接找最小的数,ans++

然后这个T了两个点,因为复杂度多了个k。正解其实只需要找每个子序列中上升序列的个数,取个max,输出减去1,因为上升的子序列可以直接合并

我的代码

#include <cstdio>
#include <iostream>
#define inf 0x3f3f3f3f3f3f3f3fLL
#define int long long
using namespace std;

struct seq
{
    int pos, n, now, x, y, p;
}a[110];

int k, len, last, ans;

void upd(int x)
{
    a[x].pos++;
    if(a[x].pos > a[x].n)
        a[x].now = inf;
    else
        a[x].now = (a[x].now * a[x].x % a[x].p + a[x].y) % a[x].p;
}

signed main()
{
    freopen("number.in", "r", stdin);
    freopen("number.out", "w", stdout); 
    scanf("%lld", &k);
    for (int i = 1; i <= k; i++)
    {
        scanf("%lld%lld%lld%lld%lld", &a[i].n, &a[i].now, &a[i].x, &a[i].y, &a[i].p);
        a[i].pos = 1;
        len += a[i].n;
    }
    last = -inf;//一开始,把last赋值极小值 
    for (int i = 1; i <= len; i++)
    {
        int m = 0;
        a[0].now = inf;
        for (int j = 1; j <= k; j++)
            if(a[j].now >= last && a[j].now < a[m].now)
                m = j;
        if(m == 0)
        {
            int mm = 0;
            for (int j = 1; j <= k; j++)
            {
                if(a[j].now < a[mm].now)
                    mm = j;
            }
            last = a[mm].now;
            ans++;
            upd(mm);
            continue;
        }
        last = a[m].now;
        upd(m);
    }
    printf("%lld\n", ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

改了

#include <cstdio>
#include <iostream>
#define inf 0x3f3f3f3f3f3f3f3fLL
#define int long long
using namespace std;

struct seq
{
    int pos, n, now, x, y, p;
}a[110];

int k, len, last, ans;

void upd(int x)
{
    a[x].pos++;
    if(a[x].pos > a[x].n)
        a[x].now = inf;
    else
        a[x].now = (a[x].now * a[x].x % a[x].p + a[x].y) % a[x].p;
}

signed main()
{
    freopen("number.in", "r", stdin);
    freopen("number.out", "w", stdout); 
    scanf("%lld", &k);
    for (int i = 1; i <= k; i++)
    {
        scanf("%lld%lld%lld%lld%lld", &a[i].n, &a[i].now, &a[i].x, &a[i].y, &a[i].p);
        a[i].pos = 1;
        int last;
        int we = 0;
        while(a[i].pos != a[i].n)
        {
            last = a[i].now;
            upd(i);
            if(a[i].now < last)
                we++;
        }
        ans=max(ans,we);
    }
    printf("%lld\n", ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

cena不资磁万能头差评

T3.密码锁

70分N<=15,100分N<=1万,所以我直接状压dp了,状压dp很简单(因为昨天刚写了个愤怒的小鸟),lc写的spfa(太强啦),我的dp是\(O(2^n*n*l)\)可能慢了点??这题路径长度为1直接bfs就行了??这

#include <cstdio>
#include <iostream>
#include <cstring>
 
using namespace std;

int N, K, L, start, maxn;
int x[20], l[110], f[1234567];

int main()
{
    freopen("lock.in", "r", stdin);
    freopen("lock.out", "w", stdout);
    scanf("%d%d%d", &N, &K, &L);
    maxn = (1 << N) - 1;
    for (int i = 1; i <= K; i++)
    {
        scanf("%d", &x[i]);
        start |= (1 << (x[i] - 1));
    }
    memset(f, 0x3f, sizeof(f));
    f[start] = 0;
    for (int i = 1; i <= L; i++)
    {
        scanf("%d", &l[i]);
        for(int g = (1 << l[i]) - 1; (g | maxn) == maxn; g <<= 1)
            for (int p = 0; p <= maxn; p++)
                f[p ^ g] = min(f[p] + 1, f[p ^ g]);
    }
    if(f[0] == 0x3f3f3f3f)
        printf("-1\n");
    else
        printf("%d\n", f[0]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

然后呢这次考试题其实不是太难,比较考察思维能力,T3实在不想改了改了就没时间tc了

然后呢这次考试是钦定四人间的???貌似能进四人间了,晚上有时间透彻了

然后呢某c和某w成绩比我高我不服(T2AC)(py交易)???

然后呢某wzy进了??

然后呢为lrt默哀3.1415936535897秒....

然后呢期待下午半天文化课把

然后呢没了(我说的有点多了)

猜你喜欢

转载自www.cnblogs.com/oier/p/9564824.html