CSP-S模拟31
CSP-S模拟31
A. 远征 (expedition)
简单题,直接大力 \(O(nV)\) 预处理 对于每个数每个位置 记录这个数下一个会被更改的位置。
查询直接跳即可,复杂度是 \(O(\log V)\)
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,c=getchar_unlocked();
for(;c>'9'||c<'0';c=getchar_unlocked());
for(;c>='0'&&c<='9';c=getchar_unlocked())
x=(x<<1)+(x<<3)+(c^48);
return x;
}
int n;
const int N=5e4+5;
unsigned short nxt[1025][N];
int a[N],b[N];
void init()
{
for(int col=1;col<1024;col++)
for(int i=n,last=n+1;i>=1;i--)
{
nxt[col][i]=last;
if((col|a[i])==col) last=i;
}
}
signed main()
{
//expedition
freopen("expedition.in","r",stdin);
freopen("expedition.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read();
init();
long long Q=read(),anss=0;
while(Q--)
{
int l=read(),r=read(),x=read();
long long ans=0;
if((x|a[l])==x) ans+=b[l],x^=a[l];
l=nxt[x][l];
while(l<=r&&x)
{
ans+=b[l];
x^=a[l];
l=nxt[x][l];
}
anss^=ans;
}
cout<<anss;
return 0;
}
B. 传送 (teleport)
以为是拦路虎,没想到是水。
显然题目的限制 \(3\) 是废话。
先特判 \(u=v\) (\(ans=0\)) 和 \(u,v\) 不在一个集合内 (\(ans=-1\)) 的情况。
先把题目中给出的四元环(偶环)画出来,发现答案至多为 \(2\)。
再手模一个三元环(奇环),发现是强连通的,再尝试加边,发现新图仍强连通。五元环同理,也是强连通的。
得到若一个连通块包含奇环,则答案为 \(1\)。
若无奇环,则如果 \(u \to v\) 路径长为偶,则答案为 \(2\)。反之答案为 \(1\)。
现在关键问题转化为如何在 \(O(n)\) 复杂度内判断该连通块是否有奇环。(当然你可以直接黑白染色判断。)
我们以惊人的注意力发现(当然你也可以从 \(s=1\) 的部分分得到启发),我们在每个连通块内任选一点跑 bfs(设为 \(S\)),记录 \(S\) 到该连通块内的每一个点 \(x\) 的路径 (\(S \to x\)) 长是否可以是偶数 / 奇数。发现若该连通块内存在奇环,则 \(S \to x\) 的路径既有奇长又有偶长。
对于无奇环,发现若 \(u \to v\) 路径长为偶 (\(ans=2\)),则 \(S \to u\) 和 \(S \to v\) 路径长奇偶性相同。反之 \(ans=1\)。
做完了。
Code:
#include<bits/stdc++.h>
// #define int long long
// #define getchar_unlocked getchar
// #define putchar_unlocked putchar
using namespace std;
inline int read()
{
int x=0,c=getchar_unlocked();
for(;c>'9'||c<'0';c=getchar_unlocked());
for(;c>='0'&&c<='9';c=getchar_unlocked())
x=(x<<1)+(x<<3)+(c^48);
return x;
}
// #ifndef ONLINE_JUDGE
// #define ONLINE_JUDGE
// #endif
const int N=1<<20;
int n,m;
vector<int> E[1<<20];
int fa[1<<20];
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
bool vis[N][2];
struct Node{
int p,cnt;
};
void bfs(int S)
{
queue<Node> q;
q.push({S,0});
vis[S][0]=1;
while(q.size())
{
Node nw=q.front();
q.pop();
nw.cnt^=1;
// cerr<<nw.p<<" "<<nw.cnt<<"\n";
for(int to:E[nw.p])
{
if(vis[to][nw.cnt]) continue;
vis[to][nw.cnt]=1;
q.push({to,nw.cnt});
}
}
}
int strong[N];
signed main()
{
// teleport
// #ifndef ONLINE_JUDGE
freopen("teleport.in","r",stdin);
freopen("teleport.out","w",stdout);
// #endif
int T=read();
n=read();
m=read();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
int fx=find(u),fy=find(v);
E[u].push_back(v);
E[v].push_back(u);
if(fx==fy) continue;
fa[fx]=fy;
}
for(int i=1;i<=n;i++)
if(vis[i][0]==0&&vis[i][1]==0) bfs(i);
for(int i=1;i<=n;i++)
if(vis[i][0]&&vis[i][1]) strong[find(i)]=1;
int Q=read();
while(Q--)
{
int u=read(),v=read();
if(u==v) { putchar_unlocked('0'); }
else if(find(u)!=find(v)) { putchar_unlocked('-'); putchar_unlocked('1'); }
else if(strong[find(u)]) { putchar_unlocked('1'); }
else putchar_unlocked((vis[u][0]^vis[v][0])?('1'):('2'));
putchar_unlocked('\n');
}
return 0;
}
C. 先辈 (anc)
小 Y 定义野兽串是 \(t=114514\)。
设 \(|S|\) 为字符串 \(S\) 的长度。
我们显然有一个 \(O(26^3|S|)\) 的做法,枚举当 \(1,4,5\) 的字符,统计答案。做 nxt 数组优化可做到 \(O(26^3\frac{3|S|}{26})\)。但还是过不了。
具体,设 \(dp[i]\) 表示长度为 \(i\) 一共有多少种情况。
转移也非常显然。
显然 \(dp\) 数组只需要开到 \(7\) 就够了。
考虑发现一些性质。
发现 \(5\) 出现至多 \(1\) 次。考虑不枚举 \(5\) 表示的字符,只枚举 \(1\) 和 \(4\)。只限制 \(5\) 不能和 \(1,4\) 相同即可。
转移同上,只修改 \(dp[4]\) 的转移方程。
如果 TLE,减少你的取模量。
Code:
#include<bits/stdc++.h>
// #define int long long
using namespace std;
const int N=5e5+5;
int totans=0;
int dp[6];
int n;
string s;
short c[N];
const int mod=114514;
int cntt=0;
int nxt[N][26];
int poss[N];
int O=0;
bool isappear[26];
void init()
{
n=s.size();
for(int col=0;col<26;col++)
for(int i=n,last=n+1;i>=0;i--)
{
nxt[i][col]=last;
if(col+'a'==s[i-1]) last=i;
}
for(int i=1;i<=n;i++) c[i]=s[i-1]-'a',isappear[c[i]]=1;
}
void dodp(int x,int y)
{
int nwwwww=totans;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<cntt;i++)
{
// cout<<poss[i]<<" "<<c[poss[i]]<<"\n";
// O++;
long long dt=0;
if(i) dt=poss[i]-poss[i-1]-1;
dp[4]=(dp[4]+dp[3]*dt)%mod;
// dp[4]%=mod;
// totans=(totans+dp[5]*dt)%mod;
if(c[poss[i]]==x)
{
dp[5]+=dp[4];
dp[2]+=dp[1];
dp[1]+=dp[0];
dp[1]%=mod;
dp[2]%=mod;
dp[5]%=mod;
}
if(c[poss[i]]==y)
{
dp[3]+=dp[2];
totans+=dp[5];
dp[3]%=mod;
totans%=mod;
}
// for(int j=1;j<=5;j++) cout<<"dp["<<j<<"]="<<dp[j]<<"\n";
// cout<<"\n";
}
// cout<<"\n";
// cout<<x+1<<" "<<y+1<<" "<<-(nwwwww-totans)<<"\n\n";
// // totans=(totans+dp[5]*(n-poss[cntt-1]))%mod;
}
// #define min(a,b,c) a<b&&a<c?a:(b<c?b:c)
// #define max(a,b,c) a>b&&a>c?a:(b>c?b:c)
void init(int x,int y)
{
if(!isappear[x]) return;
if(!isappear[y]) return;
// if(!isappear[z]) return;
int i=0;
poss[0]=min(nxt[0][x],nxt[0][y]);
while(poss[i]<=n)
{
// O++;
// poss[i+1]=poss[i]+26;
poss[i+1]=min(nxt[poss[i]][x],nxt[poss[i]][y]);
i++;
}
cntt=i;
dodp(x,y);
dodp(y,x);
// for(int j=0;j<cntt;j++) poss[j]=c[poss[j]];
// dodp(x,y,z);
// dodp(x,z,y);
// dodp(y,x,z);
// dodp(y,z,x);
// dodp(z,x,y);
// dodp(z,y,x);
}
/*
void init(int a,int b,int c)
{
int i=0;
poss[0]=min({nxt[0][a],nxt[0][b],nxt[0][c]});
int last=poss[i];
while(last<=n)
{
last=min({nxt[last][a],nxt[last][b],nxt[last][c]});
poss[i+1]=last;
i++;
}
}
*/
signed main()
{
// ios::sync_with_stdio(0);
freopen("anc.in","r",stdin);
freopen("anc.out","w",stdout);
cin>>s;
init();
for(int a=0;a<26;a++)
for(int b=a+1;b<26;b++)
init(a,b);
cout<<totans<<"\n";
// cerr<<"O="<<O<<"\n";
// #ifndef ONLINE_JUDGE
// #endif
//mt19937_64 myrand(time(0));
return 0;
}
D. 矩阵 (matrix)
数论分块。
Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int Size=(1<<20)+1;
char buf[Size],*p1=buf,*p2=buf;
char buffer[Size];
int op1=-1;
const int op2=Size-1;
#define getchar() \
(tt == ss && (tt=(ss=In)+fread(In, 1, 1 << 20, stdin), ss == tt) \
? EOF \
: *ss++)
char In[1<<20],*ss=In,*tt=In;
inline int read()
{
int x=0,c=getchar(),f=0;
for(;c>'9'||c<'0';f=c=='-',c=getchar());
for(;c>='0'&&c<='9';c=getchar())
x=(x<<1)+(x<<3)+(c^48);
return f?-x:x;
}
inline void write(int x)
{
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n,k;
void solve()
{
int ans=0;
while(n)
{
int w=n/k;
int ww=w+1;
int kk=n/ww;
int t=k-kk;
ans+=w*(t*(n-w+n-w*t)/2);
n-=w*t;
k=kk;
}
cout<<ans<<"\n";
}
signed main()
{
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
scanf("%lld%lld",&n,&k);
if(k>=n)
{
cout<<(n*(n-1))/2;
return 0;
}
solve();
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/p/19142141
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC-BY-NC-SA 4.0 协议)进行许可。

浙公网安备 33010602011771号