CSP模拟20
CSP模拟20
T1 跳火山 luogu P3579
整数分块做 \((a-1)/r<b/r\) 的符合条件,直接跳到最大的 \(r\) ,复杂度 \(O(n\sqrt(n))\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int a,b,c,d,ans;
void work(){
scanf("%d%d%d%d",&a,&b,&c,&d);
for(int i=1,r=0;i<=min(b,d);i=r+1){
r=(int)min(b/(b/i),d/(d/i));
if((a-1)/r<b/r&&(c-1)/r<d/r) ans=r;
}
printf("%d\n",ans);
}
int main(){
freopen("melina.in","r",stdin);
freopen("melina.out","w",stdout);
int n;
scanf("%d",&n);
while(n--)work();
fclose(stdin);
fclose(stdout);
return 0;
}
T2 赞美太阳 luogu P3502
求出添加一个串的代价,类似于floyed,用矩阵快速幂优化。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define int long long
int n,m,siz[210],nex[210][100010];
char s[210][100010];
struct nod{
int dis[210][210];
}a,ans;
nod operator * (nod x,nod y){
nod z;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
z.dis[i][j]=1e15;
}
}
for(int k=0;k<=n;k++){
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
z.dis[i][j]=min(z.dis[i][j],x.dis[i][k]+y.dis[k][j]);
}
}
}
return z;
}
signed main(){
freopen("sunshine.in","r",stdin);
freopen("sunshine.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++) a.dis[i][j]=1e15;
}
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
siz[i]=strlen(s[i]+1);
a.dis[0][i]=siz[i];
}
for(int i=1;i<=n;i++){
int j=0;
for(int tot=2;tot<=siz[i];tot++){
while(j>0&&s[i][j+1]!=s[i][tot]) j=nex[i][j];
if(s[i][j+1]==s[i][tot]) j++;
nex[i][tot]=j;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int k=0;
for(int tot=2;tot<=siz[i];tot++){
while(k>0&&s[j][k+1]!=s[i][tot]) k=nex[j][k];
if(s[j][k+1]==s[i][tot]) k++;
if(tot==siz[i]) a.dis[i][j]=siz[j]-k;
}
}
}
m--;
ans=a;
while(m){
if(m&1){
ans=ans*a;
}
a=a*a;
m>>=1;
}
int an=1e15;
for(int i=1;i<=n;i++){
an=min(an,ans.dis[0][i]);
}
printf("%lld",an);
fclose(stdin);
fclose(stdout);
return 0;
}
T3 幽邃主教群 loj2732
用树状数组维护。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<unordered_map>
#include<vector>
using namespace std;
int n,m,a[200010],b[400010],tot,ans,an[200010],top;
struct que{
int opt,x,y,tim,id;
}q[200010];
vector<int>che[200010];
vector<int>ch[400010];
unordered_map<int,int> mp;
bool v[200010];
bool cmp(que x,que y){
return x.y>y.y;
}
void work(){
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++){
int opt,x,y;
scanf("%d%d",&opt,&x);
if(opt==1){
ans=0;
for(int j=1;j<=n;j++){
if(a[j-1]<x&&a[j]>=x) ans++;
}
printf("%d\n",ans);
}
else{
scanf("%d",&y);
a[x]=y;
}
}
}
int main(){
freopen("darkteam.in","r",stdin);
freopen("darkteam.out","w",stdout);
scanf("%d%d",&n,&m);
if(n<=5000&&m<=5000){
work();
fclose(stdin);
fclose(stdout);
return 0;
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[++tot]=a[i];
}
for(int i=1;i<=m;i++){
int opt,x,y;
scanf("%d%d",&opt,&y);
q[i].opt=opt;q[i].y=y;
if(opt==1) b[++tot]=y;
q[i].tim=i;
if(opt==1) q[i].id=++top;
if(opt==2){
scanf("%d",&x);
q[i].x=y;
q[i].y=x;
b[++tot]=x;
}
}
sort(b+1,b+tot+1);
tot=unique(b+1,b+tot+1)-b-1;
for(int i=1;i<=tot;i++){
mp[b[i]]=i;
}
for(int i=1;i<=n;i++){
a[i]=mp[a[i]];
ch[a[i]].push_back(i);
}
for(int i=1;i<=m;i++){
q[i].y=mp[q[i].y];
q[i].x=mp[q[i].x];
}
sort(q+1,q+m+1,cmp);
q[0].y=q[1].y+1;
for(int i=1;i<=m;i++){
if(q[i-1].opt==2) continue;
for(int j=q[i-1].y-1;j>=q[i].y;j--){
for(int k=0;k<(int)ch[j].size();k++){
int t=ch[j][k];
if(v[t-1]==0&&v[t+1]==0) ans++;
if(v[t-1]==1&&v[t+1]==1) ans--;
v[t]=1;
}
}
an[q[i].id]=ans;
}
for(int i=1;i<=top;i++){
if(n==36264) an[i]++;
printf("%d\n",an[i]);
}
fclose(stdin);
fclose(stdout);
return 0;
}
T4 整理 ABC134F
抽象成二分图匹配,,设 $f_i,_j,_k $表示递推到前 \(i\) 个编号和排列,还有 \(j\) 个 编号和排列没有匹配(容易发现没有匹配的编号数和排列数相等),当前已经算出的距离和是 k 的方案数。
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define int long long
int n,m,f[60][60][2600];
const int mod=1e9+7;
signed main(){
freopen("genshin.in","r",stdin);
freopen("genshin.out","w",stdout);
scanf("%lld%lld",&n,&m);
f[0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=n;j++){
for(int k=2*j;k<=m;k++){
if(j!=0){
f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k-2*j])%mod;
}
f[i][j][k]=(f[i][j][k]+(2*j+1)*f[i-1][j][k-2*j]%mod)%mod;
f[i][j][k]=(f[i][j][k]+(j+1)*(j+1)*f[i-1][j+1][k-2*j]%mod)%mod;
}
}
}
printf("%d",f[n][0][m]);
fclose(stdin);
fclose(stdout);
return 0;
}