这篇文章上次修改于 276 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
2.3 模拟赛总结
某教练疑似在放假前安排模拟赛(卡常大赛)搞人心态,好在我都卡过了。
A
$f_0=f_1=1$
$f_i$ 定义为最小的对于所有 $k(k>0,0 \leq i-2*k)$ 满足 $f_i=f_{i-k}=f_{i-k}-f_{i-2k}$ 的正整数。
求 $f_n$
爆枚即可。
tips:有人说难度不如CSP
#include <iostream>
#include <cstdio>
#include <set>
inline int read();
int f[1005];
std::set<int>se;
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
#endif
int n=read();
f[0]=f[1]=1;
for(int i=1;i<=10000;i++){
se.insert(i);
}
for(int i=2;i<=n;i++){
for(int k=1;(i-2*k)>=0;k++){
if(2*f[i-k]-f[i-2*k]<=0){
continue;
}
auto tt=se.find(2*f[i-k]-f[i-2*k]);
if(tt!=se.end()){
se.erase(tt);
}
}
f[i]=*se.begin();
for(int k=1;(i-2*k)>=0;k++){
if(2*f[i-k]-f[i-2*k]<=0){
continue;
}
auto tt=se.find(2*f[i-k]-f[i-2*k]);
if(tt==se.end()){
se.insert(2*f[i-k]-f[i-2*k]);
}
}
}
printf("%d",f[n]);
return 0;
}
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
c=='-'?f=-1:1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return f*x;
}
/*
Anything about this program:
Type:
Description:
Example:
1:
In:
Out:
More:
*/
B
给定一个严格升序序列 $a$ ,设最大值为 $mx$。
求出最小的正整数集合 $s$ ,使得所有的对于 $i(1 \leq i\leq |s|)$ 设$F_i=$ $\{x|x \equiv 1 \pmod{s_i}\} \cap [1,mx]$ 。
使得所有的 $F_i$ 的并集为 $a$ 。
保证有解。
从小到大枚举即可。
tips: $\mathcal{O}(\frac n 1)+\mathcal{O}(\frac n2)+\mathcal{O}( \frac n 3)+…+\mathcal{O}(\frac n n)=\mathcal{O}(n\log n)$
#include <iostream>
#include <cstdio>
#include <vector>
inline int read();
bool inseq[400005];
int del[400005];
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("lcm.in","r",stdin);
freopen("lcm.out","w",stdout);
#endif
int n=read();
if(n==1){
printf("1");
return 0;
}
int lst=0;
for(int i=1;i<=n;i++){
inseq[lst=read()]=1;
}
int ans=0;
for(int i=2;i<=lst;i++){
if(del[i]==0&&inseq[i]){
ans++;
for(int j=2;(i-1)*j+1<=lst;j++){
del[(i-1)*j+1]=1;
}
}
}
printf("%d",ans);
return 0;
}
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
c=='-'?f=-1:1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return f*x;
}
/*
O(n/1)+O(n/2)+(O(n/3))+...+O(n/n)=O(nlogn)
Anything about this program:
Type:
Description:
Example:
1:
In:
Out:
More:
*/
C
求出一张图所有节点导出子图的最大独立集大小之和,$0 \leq n \leq 26$ 。
我们可以 dfs
搜索所有的独立集然后再各种转移一下,卡卡常就过了。
tips: 只要常数小,爆踩std!
#include <iostream>
#include <cstdio>
#include <vector>
inline int read();
int del[50];
int n;
int anss;
int ans[68000005];
std::vector<int>vec[50];
void dfs(int now,int sta,int ans){
if(now==n+1){
::ans[sta]=ans;
return ;
}
dfs(now+1,sta,ans);
if(del[now]==0){
for(int j=0;j<vec[now].size();j++){
del[vec[now][j]]++;
}
dfs(now+1,sta|(1<<(now-1)),ans+1);
for(int j=0;j<vec[now].size();j++){
del[vec[now][j]]--;
}
}
return ;
}
int lowbit(int x){
return x&(-x);
}
signed main(){
#ifdef ONLINE_JUDGE
#else
freopen("set.in","r",stdin);
freopen("set.out","w",stdout);
#endif
n=read();
int m=read();
for(int i=1;i<=m;i++){
int x=read()+1;
int y=read()+1;
vec[x].push_back(y);
vec[y].push_back(x);
}
dfs(1,0,0);
for(int i=0;i<(1<<n);i++){
int tt=i;
if(ans[i]!=0){
anss+=ans[i];
continue;
}
int add=0;
while(tt>0){
int temp=lowbit(tt);
tt-=lowbit(tt);
ans[i]=std::max(ans[i],ans[tt+add]);
add+=temp;
}
anss+=ans[i];
}
printf("%d",anss);
return 0;
}
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
c=='-'?f=-1:1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return f*x;
}
/*
Anything about this program:
Type:
Description:
Example:
1:
In:
Out:
More:
*/
D
求出二维平面矩阵内元素和最大值。
前缀和后继续乱搞到 $\mathcal {O} (n^3)$ 。
可以发现边界一定在正的点上,于是我们的 $n$ 实际上是 $1000$ 而不是 $2000$ 。
我们继续卡常就过了。
#include <algorithm>
#include <iostream>
#include <cstdio>
inline int read();
int X[5005];
int Y[5005];
int x[1005];
int y[1005];
int x2[1005];
int y2[1005];
int map[2005][2005];
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("ex_d5.in","r",stdin);
freopen("class.out","w",stdout);
#endif
int n=read();
int nowx=0,nowy=0;
for(int i=1;i<=n;i++){
x[i]=read();
y[i]=read();
X[++nowx]=x[i];
Y[++nowy]=y[i];
}
int m=read();
for(int i=1;i<=m;i++){
x2[i]=read();
y2[i]=read();
X[++nowx]=x2[i];
Y[++nowy]=y2[i];
}
std::sort(X+1,X+nowx+1);
nowx=std::unique(X+1,X+nowx+1)-X-1;
std::sort(Y+1,Y+nowy+1);
nowy=std::unique(Y+1,Y+nowy+1)-Y-1;
for(int i=1;i<=n;i++){
x[i]=std::lower_bound(X+1,X+nowx+1,x[i])-X;
y[i]=std::lower_bound(Y+1,Y+nowy+1,y[i])-Y;
}
for(int i=1;i<=m;i++){
x2[i]=std::lower_bound(X+1,X+nowx+1,x2[i])-X;
y2[i]=std::lower_bound(Y+1,Y+nowy+1,y2[i])-Y;
}
int a=read();
int b=read();
for(int i=1;i<=n;i++){
map[y[i]][x[i]]+=a;
}
for(int i=1;i<=m;i++){
map[y2[i]][x2[i]]-=b;
}
for(int i=1;i<=nowx;i++){
for(int j=1;j<=nowy;j++){
map[j][i]+=map[j][i-1];
map[j][i]+=map[j-1][i];
map[j][i]-=map[j-1][i-1];
}
}
std::sort(x+1,x+n+1);
std::sort(y+1,y+n+1);
register int ans=0;
for(register int ii=1;ii<=n;ii++){
register int i=y[ii];
for(register int jj=ii;jj<=n;jj++){
register int j=y[jj];
register int _min=0;
for(register int kk=1;kk<=n;kk++){
register int k=x[kk];
register int sumk;
sumk=map[j][k]-map[i-1][k];
_min=std::min(_min,sumk);
ans=std::max(ans,sumk-_min);
if(kk!=1&&x[kk]-1<=x[kk-1]){
continue;
}
k=x[kk]-1;
sumk=map[j][k]-map[i-1][k];
_min=std::min(_min,sumk);
ans=std::max(ans,sumk-_min);
}
}
}
printf("%d",ans);
return 0;
}
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
c=='-'?f=-1:1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return f*x;
}
/*
Anything about this program:
Type:
Description:
Example:
1:
In:
Out:
More:
*/