【2020省选模拟】题解
T1:
神题
显然先容斥作为下界
设下界和为
假设最后总和为
就相当于解一个方程组
解都为正整数的方案为
要求正整数把都减一即可
答案即为
为了方便将变成
考虑用范德蒙德恒等式拆开(范德蒙德恒等式对广义组合数仍成立)
这个组合数
这时候就只需要算
再拆开考虑每一位的贡献
然后用数位求出这样个东西的贡献
预处理转移时组合数系数前后缀和加快转移
总复杂度
不知道为什么跑这么慢。。。。
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline int readstr(int *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch))s[++top]=ch-'0',ch=gc();
return top;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
cs int N=15,M=515;
int D,n,C[M][M][N],pre[M][M][N],suf[M][M][N],ok[M];
int inv[M];
inline void readIn(vector<int> &a){
static int num[M*10],len;
len=readstr(num);
reverse(num+1,num+len+1);
// for(int i=1;i<=len;i++)cout<<num[i]<<" . ";puts("");
while(len){
int s=0;
for(int i=len;i;i--)
s=s*10+num[i],num[i]=s/D,s%=D;
a.pb(s);//cout<<s<<" ";
while(len&&num[len]==0)len--;
}//puts("");
}
struct bignum{
vector<int> a;
bignum(){a.clear();}
inline void clear(){a.clear();}
void read(){
readIn(a);
}
inline void del(){while(a.size()&&!a.back())a.pop_back();}
void operator ++(){
a.pb(0);a[0]++;
for(int i=0;i<a.size()-1;i++)
if(a[i]>=D)a[i]-=D,a[i+1]++;
del();
}
void operator --(){
if(!a.size())a.pb(0);a[0]--;
for(int i=0;i<(int)a.size()-1;i++)
if(a[i]<0)a[i]+=D,a[i+1]--;
del();
}
inline int len()cs{return a.size();}
friend inline bignum operator +(cs bignum &a,cs bignum &b){
bignum c;int len=max(a.len(),b.len());
c.a.resize(len);
for(int i=0;i<len;i++)c.a[i]=(a.len()>i?a.a[i]:0)+(b.len()>i?b.a[i]:0);
c.a.pb(0);
for(int i=0;i<len;i++)if(c.a[i]>=D)c.a[i]-=D,c.a[i+1]++;
c.del();return c;
}
inline int pos(int x){return a.size()>x?a[x]:0;}
inline int val(){int res=0;for(int i=(int)a.size()-1;~i;i--)res=add(mul(res,D),a[i]);return res;}
};
bignum L[N],R[N],dn;
inline void init_inv(){
inv[0]=inv[1]=1;
for(int i=2;i<M;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
}
int g[2][N],f[2][N],s[N];
inline int calc(){
memset(f,0,sizeof(f));
memset(s,0,sizeof(s));
f[1][0]=1;int cur=0;
for(int i=0;i<=510;i++){
int lim=dn.pos(i);
memcpy(g,f,sizeof(g));
memset(f,0,sizeof(f));
for(int x=0;x<n;x++)if(g[0][x]||g[1][x]){
int now=add(g[0][x],g[1][x]);
for(int y=0;x+y<n;y++){
if(lim)Add(f[0][x+y],mul(now,pre[i][lim-1][y]));
if(lim+1<D){
Add(f[1][x+y],mul(now,suf[i][lim+1][y]));
if(i+1>=dn.len())Add(s[x+y],mul(now,suf[i][lim+1][y]));
}
for(int t=0;t<2;t++)
Add(f[t][x+y],mul(g[t][x],C[i][lim][y]));
if(i+1==dn.len())Add(s[x+y],mul(g[1][x],C[i][lim][y]));
}
}
}
int v=dec(0,dn.val()),res=0,c=1;
for(int i=0;i<n;i++){
if(i)c=mul(c,mul(dec(v,i-1),inv[i]));
Add(res,mul(s[n-1-i],c));
}
return res;
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read(),D=read(),init_inv();
for(int i=0;i<D;i++)ok[i]=read();
for(int i=1;i<=n;i++)L[i].read(),R[i].read(),--L[i];
for(int i=0,pw=1,mt;i<=510;i++,Mul(pw,D)){
for(int d=0;d<D;d++)if(ok[d]){
C[i][d][0]=1,mt=mul(pw,d);
for(int j=1;j<=n;j++)
C[i][d][j]=mul(C[i][d][j-1],mul(dec(mt+1,j),inv[j]));
}
for(int j=0;j<=n;j++)pre[i][0][j]=C[i][0][j];
for(int d=1;d<D;d++)
for(int j=0;j<n;j++)
pre[i][d][j]=add(pre[i][d-1][j],C[i][d][j]);//,cout<<pre[i][d][j]<<'\n';;
for(int j=0;j<=n;j++)suf[i][D-1][j]=C[i][D-1][j];
for(int d=D-2;~d;d--)
for(int j=0;j<n;j++)
suf[i][d][j]=add(suf[i][d+1][j],C[i][d][j]);//cout<<suf[i][d][j]<<'\n';
}
int res=0;
for(int s=0;s<(1<<n);s++){
dn.clear();int siz=0;
for(int i=0;i<n;i++)
if(s&(1<<i))siz++,dn=dn+R[i+1];
else dn=dn+L[i+1];
// for(int i=0;i<dn.a.size();i++)cout<<dn.a[i]<<" ";puts("");
++dn;
if(siz&1)Dec(res,calc());
else Add(res,calc());
}
cout<<res<<'\n';
}
T2:
预处理每两点间距离枚举两条边分类讨论贡献即可
没考虑一条边的情况。。。
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=5005;
int dis[N][N];
vector<pii> e[N];
struct edge{
int u,v,w;
}E[N];
int n,m,ans,vis[N];
priority_queue<pii,vector<pii>,greater<pii> > q;
inline void dijkstra(int str,int *dis){
memset(vis,0,sizeof(int)*(n+1));
dis[str]=0;q.push(pii(0,str));
while(!q.empty()){
int u=q.top().se;q.pop();
if(vis[u])continue;vis[u]=1;
for(pii &x:e[u]){
if(dis[x.fi]>dis[u]+x.se){
dis[x.fi]=dis[u]+x.se;
q.push(pii(dis[x.fi],x.fi));
}
}
}
}
inline int calc(int a,int b,int c,int d,int lx,int ly){
chemn(ly,(b-a)/2),chemn(lx,(c-a)/2);
return a+min(lx+ly,(d-a)/2);
}
inline int calc(edge x,edge y){
int a=dis[x.u][y.u],b=dis[x.u][y.v],c=dis[x.v][y.u],d=dis[x.v][y.v],e=x.w,f=y.w;
return max(max(calc(a,b+f,c+e,d+e+f,e,f),calc(b,a+f,d+e,c+e+f,e,f)),max(calc(c,d+f,a+e,b+e+f,e,f),calc(d,c+f,b+e,a+e+f,e,f)));
}
inline void solve(){
n=read(),m=read(),ans=0;
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read()*2;
E[i].u=u,E[i].v=v,E[i].w=w;
chemx(ans,w/2);
e[u].pb(pii(v,w)),e[v].pb(pii(u,w));
}
for(int i=1;i<=n;i++){
memset(dis[i],127/3,sizeof(int)*(n+1));
dijkstra(i,dis[i]);
}
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
chemx(ans,calc(E[i],E[j]));
printf("%.1lf\n",1.0*ans/2);
for(int i=1;i<=n;i++)
memset(dis[i],0,sizeof(int)*(n+1)),e[i].clear();
}
int main(){
int T=read();
while(T--)solve();
}
T3:
凸包
考虑先枚举一个凸包的最左端点
其余点按照极角排序
设表示当前凸包最后一个点为,上一个点为的方案数
考虑枚举转移
由于要满足凸包性质,所以可以按照的极角利用单调性转移
然后按对于极角从大到小对于每个判断一下是否有点在的三角形内即可
复杂度
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
cs int N=505;
struct pt{
int x,y;
pt(int _x=0,int _y=0):x(_x),y(_y){}
friend inline pt operator +(cs pt &a,cs pt &b){return pt(a.x+b.x,a.y+b.y);}
friend inline pt operator -(cs pt &a,cs pt &b){return pt(a.x-b.x,a.y-b.y);}
friend inline int operator *(cs pt &a,cs pt &b){return a.x*b.y-a.y*b.x;}
}p[N];
inline int cross(int a,int b,int c){
return (p[a]-p[c])*(p[b]-p[c]);
}
int tp;
inline bool cmp(cs int &a,cs int &b){
return cross(a,b,tp)>0;
}
inline bool comp(cs pt &a,cs pt &b){
return a.x==b.x?a.y<b.y:a.x<b.x;
}
int f[N][N],id[N][N*2],ql[N],qr[N],tl,tr;
int n,ans;
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read();
for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read();
sort(p+1,p+n+1,comp);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)id[i][j]=j;
id[i][i]=1;tp=i;
sort(id[i]+2,id[i]+i+1,cmp);
sort(id[i]+i+1,id[i]+n+1,cmp);
for(int j=n+1;j<2*n;j++)id[i][j]=id[i][j-n+1];
}
for(int i=1;i<=n;i++){
memset(f,0,sizeof(f));
for(int j=i+1;j<=n;j++){
int p=id[i][j],ps=0;
tl=tr=0;
for(int k=2;k<=n;k++)if(id[p][k]==i){ps=k;break;}
for(int k=ps;k<ps+n;k++)if(id[p][k]>i){
if(cross(id[p][k],i,p)>0)qr[++tr]=id[p][k];
else ql[++tl]=id[p][k];
}
int s=0;
for(int l=1,r=1;r<=tr;){
if(l>tl||cross(ql[l],qr[r],p)>0)
Add(f[p][qr[r]],s),r++;
else Add(s,f[ql[l]][p]),l++;
}
int pre=0;
while(tr){
if(!pre||cross(qr[tr],pre,i)>0)
Add(f[p][qr[tr]],1),pre=qr[tr];
else f[p][qr[tr]]=0;
tr--;
}
for(int k=j+1;k<=n;k++)Add(ans,f[p][id[i][k]]);
}
}
cout<<ans<<'\n';
}