8 月 15 日做题日记
八月 15 日刷题日记
早上的 CF:
CF1547F Array Stabilization (GCD version)
一天一道思维题。
其实结论猜到了大半,但是没想到倍增优化,去看了一眼 CF 官方题解。
下标这样安排是为了首尾相接,首先看懂这个。
设操作次数是 ,手摸样例我们知道:
-
时,
-
时,
一个非常 naive 的就是 ST 表处理区间 ,ST 表对有重复无影响的操作有着妙用。
再者是这个 具有单调性,很显然的是 如果满足条件,那么 必满足条件。
复杂度 ST ,二分加个 ,判断 ,总体大概 ,常数比那些写线段树的小多了。
瞎凑的模拟赛
全都是随机跳题。
P7411 [USACO21FEB] Comfortable Cows S
题目的暗示很明显就是递推。
对于每个新加进去的点 dfs 修改即可。
// Author: Gym_nastics
// Date: 2022-8-15
// Powered by VS Code
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
//#define int long long
const int Mod=1e9+7;
const int N=1e6+7,M=4e3+1;
using namespace std;
inline int read() {
int x=0,f=0;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) f|=(ch=='-');
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
return f?-x:x;
}
void print(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
}
int n,ans;
int mp[M][M];
const int dx[]={0,1,-1,0,0};
const int dy[]={0,0,0,1,-1};
inline void dfs(int x, int y) {
if(!mp[x][y]) return ;
int res = 0;
pair<int,int> rest;
for(int k=1;k<=4;k++) {
int nx = x + dx[k], ny = y + dy[k];
if(mp[nx][ny]) res ++;
else rest = make_pair(nx,ny);
}
if(res != 3) return;
mp[x = rest.first][y = rest.second] = 1;
ans ++;
for(int k=0;k<=4;k++) {
int nx = x + dx[k], ny = y + dy[k];
dfs(nx, ny);
}
}
signed main() {
n=read();
for(int i=1;i<=n;i++){
int x=read()+1001,y=read()+1001;
if(mp[x][y]) ans--;
mp[x][y]=1;
for(int k=0;k<=4;k++) dfs(x+dx[k],y+dy[k]);
printf("%d\n",ans);
}
return 0;
}
P7687 [CEOI2005] Critical Network Lines
一坨题目其实就是让我们找割边,啥割边满足题意?
因为俩都无了才算数,所以要么联通块一边啥也有,要么一边啥也没有。
然后就做完了。
// Problem: P7687 [CEOI2005] Critical Network Lines
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7687
// Memory Limit: 64 MB
// Time Limit: 3000 ms
// Author: Gym_nastics
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
//#define int long long
const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;
using namespace std;
inline int read() {
int x=0,f=0;
char ch=getchar();
while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
return f?-x:x;
}
vector<int>G[N];
int n,m,dfn[N],low[N],idx;
int a[N],b[N],k,l;
vector<pair<int,int> >A;
void tarjan(int u,int fa){
dfn[u]=low[u]=++idx;
for(auto &v:G[u]){
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
if(!a[v]||!b[v]||a[v]==k||b[v]==l)
A.push_back(make_pair(u,v));
}
a[u]+=a[v],b[u]+=b[v];
}if(v!=fa) low[u]=min(low[u],dfn[v]);
}
}
signed main() {
n=read();m=read();k=read(),l=read();
for(int i=1;i<=k;i++) a[read()]=1;
for(int i=1;i<=l;i++) b[read()]=1;
for(int i=1;i<=m;i++){
int u=read(),v=read();
G[u].push_back(v);
G[v].push_back(u);
}
tarjan(1,0);
printf("%d\n",A.size());
// sort(A.begin(),A.end());
for(auto &I:A) printf("%d %d\n",I.first,I.second);
return 0;
}
剩下俩暴力不想打。
T3 正解是个 SA,T4 正解是个左偏树?@Lxyiiiiii
下午的 NOIp 计划
P3694 邦邦的大合唱站队
状压 DP。但是我不会……
// Problem: P3694 邦邦的大合唱站队
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3694
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Author: Gym_nastics
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
//#define int long long
const int Mod=1e9+7;
const int N=1e5+7,M=2e3+1;
using namespace std;
inline int read() {
int x=0,f=0;
char ch=getchar();
while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
return f?-x:x;
}
int n,m;
int f[1<<20],s[1<<20],sum[N][21];
signed main() {
n=read(),m=read();
for(int i=1;i<=n;i++){
int a=read();
for(int j=1;j<=m;j++) sum[i][j]=sum[i-1][j];
++sum[i][a];
}
for(int i=0;i<(1<<m);i++){
int a=i,cnt=0;
while(a){
++cnt;
if(a&1) s[i]+=sum[n][cnt];
a>>=1;
}
f[i]=INF;
}f[0]=0;
for(int i=0;i<(1<<m);i++){
for(int j=1;j<=m;j++){
if((i>>(j-1)&1)){
int l=s[i^(1<<(j-1))],r=s[i];
f[i]=min(f[i],f[i^(1<<(j-1))]+sum[n][j]-(sum[r][j]-sum[l][j]));
}
}
}
return 0%printf("%d\n",f[(1<<m)-1]);
}
CF11D A Simple Task
状压。
设 为当前点为 ,状态为 时方案数。
并且强制令第一个经过的点为最小点,以后加入的点不能比它小,这个可以用 lowbit
来求。然后如果枚举点和起点重了,说明找到环,因为是无向图,所以相邻两点之间也算了一遍,相减除二就是答案。
// Problem: CF11D A Simple Task
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF11D
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// Author: Gym_nastics
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long
const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;
using namespace std;
inline int read() {
int x=0,f=0;
char ch=getchar();
while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
return f?-x:x;
}
#define lowbit(x) (x&-x)
int n,m,f[20][1<<20],Ans;
vector<int>G[20];
signed main() {
n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read()-1,v=read()-1;
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=0;i<n;i++) f[i][1<<i]=1;
for(int i=0;i<(1<<n);i++){
for(int j=0;j<n;j++){
if(!f[j][i]) continue;
for(auto &v:G[j]){
if(lowbit(i)>(1<<v)) continue;
if(i&(1<<v)){if(lowbit(i)==(1<<v)) Ans+=f[j][i];}
else f[v][i|(1<<v)]+=f[j][i];
}
}
}
return 0&printf("%lld\n",(Ans-m)>>1);
}
CF222E Decoding Genome
因为 scanf
调了大半个小时((( 警钟长鸣。
一个没什么难度的 dp + 矩阵快速幂,设 为前 位最后一个字符为 的方案数,显然的转移:
ck
是判断合法不合法,然后这是个矩阵乘法的形式,直接矩阵快速幂:
即为最终答案,统计 就行了。
// Problem: CF222E Decoding Genome
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF222E
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// Author: Gym_nastics
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long
const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;
using namespace std;
inline int read() {
int x=0,f=0;
char ch=getchar();
while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
return f?-x:x;
}
int n,m,k;
struct mx{
int x[61][61];
mx(){memset(x,0,sizeof x);}
}A,B;
mx operator *(mx a,mx b){
mx res;
for(int i=1;i<=60;i++)
for(int k=1;k<=60;k++)
for(int j=1;j<=60;j++)
res.x[i][j]=(res.x[i][j]+a.x[i][k]*b.x[k][j])%Mod;
return res;
}
mx Pow(mx a,int b){
mx res;
for(int i=0;i<=60;i++) res.x[i][i]=1;
while(b){
if(b&1) res=res*a;
b>>=1;a=a*a;
}
return res;
}
int jb(char ch){
if(ch>='a'&&ch<='z') return ch-96;
return ch-38;
}
signed main() {
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
A.x[i][j]=1;
for(int i=1;i<=k;i++){
char a,b;
cin>>a>>b;
A.x[jb(b)][jb(a)]=0;
}
for(int i=1;i<=60;i++) B.x[1][i]=1;
A=Pow(A,n-1);B=B*A;
int Ans=0;
for(int i=1;i<=m;i++) Ans+=B.x[1][i],Ans%=Mod;
return 0&printf("%lld\n",Ans);
}
晚上
浅做一手 ATcoder 的 DP contest 练一下。
水题就不发了,发一下有思考的题目。
AT4526 Knapsack 2
乍一看 01 背包,一看 W 的范围,玩你妈。
然后注意的是极小的 和 ,那可不可以这么设背包?
为价值为 时最小的体积,然后就没了…
// Problem: AT4526 Knapsack 2
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/AT4526
// Memory Limit: 1000 MB
// Time Limit: 2000 ms
// Author: Gym_nastics
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long
const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;
using namespace std;
inline int read() {
int x=0,f=0;
char ch=getchar();
while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
return f?-x:x;
}
int n,W,v[N],w[N],f[N],_;
signed main() {
n=read(),W=read();_=n*1000;
for(int i=1;i<=n;i++) w[i]=read(),v[i]=read();
memset(f,INF,sizeof f);
f[0]=0;
for(int i=1;i<=n;i++){
for(int j=_;j>=v[i];j--)
f[j]=min(f[j],f[j-v[i]]+w[i]);
}
for(int i=_;i;i--)
if(f[i]<=W) return printf("%d\n",i),0;
return 0;
}
总结
做了 14 道题,有67道AT的 Ed DP Contest ……
晚上帮一位初一OIer了个题。
总的来说还不错。
本文作者:Gym_nastics
本文链接:https://www.cnblogs.com/BlackDan/p/16589846.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(一):从.NET IoT入
· .NET 开发的分流抢票软件,不做广告、不收集隐私
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· 开箱你的 AI 语音女友「GitHub 热点速览」
· 前端实现 HTML 网页转 PDF 并导出