码迷,mamicode.com
首页 > 其他好文 > 详细

csp-s模拟测试b组加餐antipalindome,randomwalking,string题解

时间:2019-09-27 19:41:07      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:lan   颜色   bsp   问题   view   字母   ace   style   规律   

题面:https://www.cnblogs.com/Juve/articles/11599318.html

antipalindome:

打表找规律?

对于一个回文串,我们只要保证3位以内不回文即可,即只要不出现三位以内回文就合法

对于前三位:m*(m-1)*(m-2),剩下的n-3个位置用m-2来填

所以$ans=m*(m-1)*(m-2)^(n-2)$,注意边界的判断

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
const int mod=1e9+7;
const int phi=1e9+6;
int t,n,m,ans=0;
int q_pow(int a,int b,int p){
	a%=p;
	(b+=(p-1))%=(p-1);
	int res=1;
	while(b){
		if(b&1) res=res*a%p;
		a=a*a%p;
		b>>=1;
	}
	return res%p;
}
signed main(){
	scanf("%lld",&t);
	while(t--){
		ans=0;
		scanf("%lld%lld",&n,&m);
		if(n==1){
			printf("%lld\n",m%mod);
			continue;
		}else if(m==1){
			puts("0");
			continue;
		}else if(m==2&&n==2){
			puts("2");
			continue;
		}else{
			ans=q_pow(m-2,n-2,mod)%mod;
			for(int i=m;i>=m-1;--i){
				(ans*=(i%mod))%=mod;
			}
			printf("%lld\n",ans);
		}
	}
	return 0;
}

randomwalking:

树形dp,感觉它贼麻烦,博主也是不会了

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
const int MAXN=1e6+4;
const double inf=110000000000000000.0;
int n,a[MAXN],du[MAXN],ans;
int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
void add(int u,int v){
    ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
}
double f[MAXN],g[MAXN],minn=inf;
void dfs(int x,int fa){
    f[x]=(double)a[x];
    if(du[x]==1&&fa!=0){
        return ;
    }
    for(int i=pre[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa) continue;
        dfs(y,x);
        if(fa!=0&&du[x]!=1) f[x]+=(double)f[y]/(double)((double)du[x]-1.0);
        else f[x]+=(double)f[y]/du[x];
    }
}
void DFS(int x,int fa){
    for(int i=pre[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa) continue;
        g[y]=(double)a[y];
        double tmp1=(double)(g[x]-(double)a[x])*(double)du[x];
        double tmp2=tmp1-f[y];
        double tmp3=(double)(f[y]-(double)a[y])*(double)(du[y]-1.0);
        if(du[x]>1) g[y]+=(double)(tmp2/(double)(du[x]-1.0)+(double)a[x]+tmp3)/(double)(du[y]);
        else g[y]+=(double)((double)a[x]+tmp3)/(double)(du[y]);
        DFS(y,x);
    }
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;++i){
        scanf("%lld",&a[i]);
    }
    for(int i=1,u,v;i<n;++i){
        scanf("%lld%lld",&u,&v);
        add(u,v),add(v,u);
        ++du[u],++du[v];
    }
    dfs(1,0);
    g[1]=f[1];
    DFS(1,0);
    minn=g[1],ans=1;
    for(int i=1;i<=n;++i){
        if(g[i]<minn){
            ans=i;
            minn=g[i];
        }
    }
    printf("%lld\n",ans);
    return 0;
}

string:

先翻转,然后用并差集维护相同颜色的位置

然后把k化成26进制数,对于不能确定的点用k的26进制数去确定

区间反转用平衡树

我们给 ′ a ′ 到 ′ z ′ 编号为 [1, 26] ,再给每个 ′ ? ′ 一个大于 26 的不同的标号,输入的串变成了一个这样的数字串,计
为 S .
我们直接对这个数字串去做操作,得到一个新的数字串,记为 T .
这件事就是这个经典的问题bzoj3223:Tyvj1729文艺平衡树.
直接把 S 和 T 的每一位用并查集并起来,表示这些标号所代表的字符一定是相同的.
如果一个联通块内包含至少一个字母,那么这个联通块的字符都确定了.
否则有 26 种可能,扫一遍直接分配即可.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
#define int long long
using namespace std;
const int MAXN=5e5+5;
int n,m,k,l[MAXN],r[MAXN],b[MAXN];
char ch[MAXN];
bool pd[MAXN];
struct node1{
	int val,pos;
}a[MAXN];
int fa[MAXN];
int find(int x){
	return fa[x]=(fa[x]==x?x:find(fa[x]));
}
void merge(int x,int y){
	x=find(x),y=find(y);
	fa[max(x,y)]=min(x,y);
}
vector<int>v[MAXN];
int col[MAXN],tot=-1;
struct Node{
    bool rev;
    int s,h,v;
    Node *l,*r;
}*root=0;
struct tbw{
    Node *l,*r;
    tbw(){}
    tbw(Node *a,Node *b){l=a,r=b;}
};
int gets(Node *x){return x?x->s:0;}
void update(Node *x){x->s=gets(x->l)+1+gets(x->r);}
void rev(Node *x){
    if(!x) return;
    x->rev ^=1;
    swap(x->l,x->r);
}
void down(Node *x){
    if(x->rev) rev(x->l),rev(x->r),x->rev=0;
}
Node *merge(Node *a,Node *b){
    if(!a) return b;
    if(!b) return a;
    if (a->h<b->h){
        down(a);
        a->r=merge(a->r,b);
        update(a);
        return a;
    }
    down(b);
    b->l=merge(a,b->l);
    update(b);
    return b;
}
tbw split(Node *x,int k){
    if(!x) return tbw(0,0);
    down(x);
    int tot=gets(x->l)+1;
    if(k<tot){
        tbw a=split(x->l,k);
        x->l=a.r;
        update(x);
        return tbw(a.l,x);
    }
    tbw a=split(x->r,k-tot);
    x->r=a.l;
    update(x);
    return tbw(x,a.r);
}
void insert(int v){
    Node *x=new Node;
    x->h=rand(),x->l=x->r=0;
    x->v=v,x->s=1;
    root=merge(root,x);
}
void rev(int l,int r){
    tbw a=split(root,l-1);
    tbw b=split(a.r,r-l+1);
    rev(b.l);
    root=merge(merge(a.l,b.l),b.r);
}
int num=0;
void print(Node *x){
    if(!x) return;
    down(x);
    print(x->l);
	b[++num]=x->v;
    print(x->r);
}
signed main(){
	scanf("%lld%lld%lld",&n,&m,&k);
	scanf("%s",ch+1);
	for(int i=1;i<=n;++i){
		fa[i]=a[i].pos=b[i]=i;
		a[i].val=0;
		if(ch[i]!=‘?‘){
			a[i].val=ch[i]-‘a‘+1;
			pd[i]=1;
		}
		insert(i);
	}
	for(int i=1;i<=m;++i){
		scanf("%lld%lld",&l[i],&r[i]);
		rev(l[i],r[i]);
	}
	print(root);
	for(int i=1;i<=n;++i){
		merge(b[i],i);
	}
	for(int i=1;i<=n;++i){
		int x=find(i);
		v[x].push_back(i);
		if(a[x].val!=0) col[x]=a[x].val;
		else if(a[i].val!=0) col[x]=a[i].val;
	}
	for(int i=1;i<=n;++i){
		int x=find(i);
		if(col[x]==0) continue;
		a[i].val=col[x];
	}
	for(int i=1;i<=n;++i){
		if(col[i]==0&&v[i].size()!=0) ++tot;
	}
	for(int i=1;i<=n;++i){
		int x=find(i);
		if(a[i].val!=0) continue;
		else if(x!=i) a[i].val=a[x].val;
		else if(tot>13) a[i].val=1,--tot;
		else{
			int p=pow(26,tot--);
			int x=k/p;
			if(k%p) ++x;
			a[i].val=x--;
			k-=x*p;
		}
	}
	for(int i=1;i<=n;++i){
		putchar(a[i].val+‘a‘-1);
	}
	puts("");
	return 0;
}

 

csp-s模拟测试b组加餐antipalindome,randomwalking,string题解

标签:lan   颜色   bsp   问题   view   字母   ace   style   规律   

原文地址:https://www.cnblogs.com/Juve/p/11599329.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!