T1:
组合数
题目要求:
推一下:
代码:
#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;
}