【NOIP模拟】T1+T2+T3

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38083668/article/details/83093550

T1

     组合数

     题目要求:

    \sum_{j=l}^{r}\begin{pmatrix} j\\ k_{i}+j-l \end{pmatrix}

    推一下:
    \sum_{j=l}^{r}\begin{pmatrix} j\\ k_{i}+j-l \end{pmatrix}= \sum_{j=l}^{r}\begin{pmatrix} j\\ l-k_{i} \end{pmatrix}= C_{r+1}^{l-k_{i}+1}-C_{l}^{l-k_{i}+1}

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int mod=1e9+7;
const int Max=100010;
int n,m,ans=1,sum;
int mul[Max],inv[Max];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(int x)
{
	if(x>9) print(x/10);
	putchar('0'+x%10);
}

inline int ksm(int a,int b)
{
	int ans=1;
	a%=mod;
	while(b)
	{
	  if(b&1) ans=(ans*a)%mod;
	  b>>=1;
	  a=(a*a)%mod;
	}
	return ans;
}

inline void pre()
{
	mul[0]=inv[0]=inv[1]=1;
	for(int i=1;i<=n+5;i++) mul[i]=(mul[i-1]*i)%mod;
	for(int i=2;i<=n+5;i++) inv[i]=ksm(mul[i],mod-2);
}

inline int C(int n,int m)
{
	if(n>=0&&m>=0&&n>=m) return (mul[n]*inv[n-m]%mod*inv[m])%mod;
	return 0;
}

signed main()
{
	n=get_int(),m=get_int();
	pre();
	for(int i=1;i<=m;i++)
	{
	  int l=get_int(),r=get_int(),k=get_int();
	  ans=(ans*(C(r+1,l-k+1)-C(l,l-k+1)))%mod;
	}
	print((ans%mod+mod)%mod);
	return 0;
}

T2

     基环树+并查集。

     基环树就能满足题目要求,用类似求最小生成树的方法贪心的加边维护即可。

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int Max=500010;
int n,m,ans;
int fa[Max],tag[Max];
struct shu{int x,y,z;}e[Max];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline bool comp(const shu &a,const shu &b){return a.z<b.z;}
inline int get(int v){return fa[v]==v?v:fa[v]=get(fa[v]);}

signed main()
{
	n=get_int(),m=get_int();
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++) e[i].x=get_int(),e[i].y=get_int(),e[i].z=get_int();
	sort(e+1,e+m+1,comp);
	for(int i=1;i<=m;i++)
	{
	  int fax=get(e[i].x),fay=get(e[i].y);
	  if(fax==fay&&!tag[fax]) tag[fax]=1,fa[fax]=fay,ans+=e[i].z;
	  else
	  {
	  	if(tag[fax]&tag[fay]) continue;
	  	tag[fay]|=tag[fax],fa[fax]=fay,ans+=e[i].z;
	  }
	}
	cout<<ans;
	return 0;
}

T3

     主席树+字符串哈希。

     排序时比较两串中第一个不同的地方即可。

代码:

#include <bits/stdc++.h>
using namespace std;

const int Max=100010;
int n,m,tot;
int sum[Max*20],lc[Max*20],rc[Max*20],root[Max*20],ans[Max];
unsigned long long tree[Max*20],Pow[Max];
char ch[Max];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(int x)
{
	if(x>9) print(x/10);
	putchar('0'+x%10);
}

inline void build(int &now,int l,int r)
{
	now=++tot,sum[now]=r-l+1;
	if(l==r) {tree[now]=ch[l]-'a'+1;return;}
	int mid=(l+r)>>1;
	build(lc[now],l,mid),build(rc[now],mid+1,r);
	tree[now]=tree[lc[now]]*Pow[sum[rc[now]]]+tree[rc[now]];
}
inline void add(int fa,int &now,int l,int r,int pos,char c)
{
	now=++tot,lc[now]=lc[fa],rc[now]=rc[fa],sum[now]=sum[fa];
	if(l==r){tree[now]=c-'a'+1;return;}
	int mid=(l+r)>>1;
	if(pos<=mid) add(lc[fa],lc[now],l,mid,pos,c);
	else add(rc[fa],rc[now],mid+1,r,pos,c);
	tree[now]=tree[lc[now]]*Pow[sum[rc[now]]]+tree[rc[now]];
}
inline int Q(int fa1,int fa2,int l,int r)
{
	if(l==r) return tree[fa1]<tree[fa2]?-1:1;
	int mid=(l+r)>>1;
	if(tree[lc[fa1]]!=tree[lc[fa2]]) return Q(lc[fa1],lc[fa2],l,mid);
	return Q(rc[fa1],rc[fa2],mid+1,r);
}
inline bool comp(const int &a,const int &b)
{
	if(tree[root[a]]==tree[root[b]]) return a<b;
	return Q(root[a],root[b],1,m)<0;
}

int main()
{
	n=get_int(),m=get_int(),scanf("%s",ch+1),Pow[0]=1,ans[1]=1;
	for(int i=1;i<=n;i++) Pow[i]=Pow[i-1]*131;
	build(root[1],1,m);
	for(int i=2;i<=n;i++)
	{
	  int fa=get_int(),pos=get_int();scanf("%s",ch+1);
	  add(root[fa],root[i],1,m,pos,ch[1]),ans[i]=i;
	}
	std::sort(ans+1,ans+n+1,comp);
	for(int i=1;i<=n;i++) print(ans[i]),putchar(' ');
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/83093550
今日推荐