为了让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秒....
然后呢期待下午半天文化课把
然后呢没了(我说的有点多了)