(貌似是远古大坑了
T1 bzoj 4737 组合数问题
题目大意:
给定 $n,m$ 求有多少个$C_n^m$整除$k$ $(n,m le 10^{18})$
思路:
考虑如何计算组合数 使用lucas只有在lucas递归过程中n<m才会产生0
因此我们考虑把$n,m$按照k进制分解 只要中间某一位n<m即满足题意
可以数位dp 由于统计补集比较简单 所以统计补集即中间所有数$m le n$
$dp space i space j space k$表示到了第i位 是否卡在了$n,m$的边界上 转移非常好转移
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define ll long long 11 #define inf 2139062143 12 #define rep(i,s,t) for(int i=(s);i<=(t);++i) 13 #define dwn(i,s,t) for(int i=(s);i>=(t);--i) 14 #define ren for(int i=fst[x];i;i=nxt[i]) 15 #define Fill(x,t) memset(x,t,sizeof(x)) 16 #define MAXN 100 17 #define MOD 1000000007 18 using namespace std; 19 inline ll read() 20 { 21 ll x=0,f=1;char ch=getchar(); 22 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 23 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 24 return x*f; 25 } 26 ll n,m,T,p,dp[MAXN][2][2],a[MAXN],la,b[MAXN],lb,ans; 27 ll q_pow(ll bas,ll t) 28 { 29 ll res=1; 30 for(;t;t>>=1,(bas*=bas)%=MOD) 31 if(t&1) (res*=bas)%=MOD; 32 return res; 33 } 34 inline ll inv(ll x) {return q_pow(x,MOD-2);} 35 int main() 36 { 37 T=read(),p=read();ll inv2=inv(2);int lx,ly; 38 while(T--) 39 { 40 n=read(),m=read(),m=min(n,m),la=lb=0LL;Fill(dp,0);Fill(a,0);Fill(b,0); 41 ans=(((((m%MOD)*((m+1)%MOD))%MOD)*inv2)%MOD+(((n-m+1)%MOD)*((m+1)%MOD))%MOD)%MOD; 42 while(n) a[++la]=n%p,n/=p;while(m) b[++lb]=m%p,m/=p; 43 dp[la+1][1][1]=1; 44 dwn(i,la,1) rep(j,0,1) rep(k,0,1) 45 if(dp[i+1][j][k]) 46 { 47 if(j) lx=a[i];else lx=p-1; 48 if(k) ly=b[i];else ly=p-1; 49 rep(x,0,lx) rep(y,0,min(ly,x)) (dp[i][j&(x==a[i])][k&(y==b[i])]+=dp[i+1][j][k])%=MOD; 50 } 51 rep(i,0,1) rep(j,0,1) (ans+=MOD-dp[1][i][j])%=MOD; 52 printf("%lld ",ans); 53 } 54 }
T2 bzoj 4738 汽水
题目大意:
在树上求一条路径使得这个路径的边权平均值最接近$K$ 求这个最小差值
思路:
这种东西很容易想到点分治,我们对于所有初始边权都减去$K$,这样就是求最接近$0$的路径
对于分治重心内的所有路径,维护三个值:路径总长,路径上边数,来自哪一个子树
我们对于总长排序后可以二分一个值,判断能否存在两个路径拼起来差值满足mid
把式子转化为$sum-num imes x$其中$x$为二分出的mid 这样只要分别$check (pm mid)$
写两个check即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #include<set> 11 #include<complex> 12 #include<iomanip> 13 #define Fill(a,x) memset(a,x,sizeof(a)) 14 #define rep(i,s,t) for(register int i=(s),i__end=(t);i<=i__end;++i) 15 #define dwn(i,s,t) for(register int i=(s),i__end=(t);i>=i__end;--i) 16 #define ren for(int i=fst[x];i;i=nxt[i]) 17 #define inf 1LL<<60 18 #define ll long long 19 #define ull unsigned long long 20 #define MAXN 50100 21 #define MOD 998244353 22 using namespace std; 23 inline ll read() 24 { 25 ll x=0,f=1;char ch=getchar(); 26 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 27 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 28 return x*f; 29 } 30 struct data {int num,bl;ll val;}g[MAXN],A,B; 31 bool operator < (data a,data b) {return a.val<b.val;} 32 int n,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt,sz[MAXN],mx[MAXN],Sum,Mx,rt,len,vis[MAXN]; 33 ll val[MAXN<<1],K,ans=inf; 34 void add(int u,int v,ll w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;} 35 void getrt(int x,int pa) 36 { 37 mx[x]=0,sz[x]=1;ren if(to[i]^pa&&!vis[to[i]]) getrt(to[i],x),sz[x]+=sz[to[i]],mx[x]=max(mx[x],sz[to[i]]); 38 mx[x]=max(mx[x],Sum-sz[x]);if(mx[x]<Mx) Mx=mx[x],rt=x; 39 } 40 void Get(int x,int pa,int dep,int frm,ll dis) 41 { 42 g[++len]=(data){dep,frm,dis}; 43 ren if(to[i]^pa&&!vis[to[i]]) Get(to[i],x,dep+1,frm,dis+val[i]); 44 } 45 int pos; 46 void upd(data x) 47 { 48 if(B<x) return ; 49 if(x<A) {if(x.bl!=A.bl) B=A;A=x;}else if(x.bl!=A.bl) B=x; 50 } 51 int cheq(ll x) 52 { 53 A=B=(data){0,0,inf};int j=pos-1; 54 rep(i,pos,len) 55 { 56 for(;j&&g[i].val+g[j].val>=0;j--) upd((data){0,g[j].bl,g[j].val-x*g[j].num}); 57 if((A.bl==g[i].bl?B.val:A.val)<(ll)x*g[i].num-g[i].val) return 1; 58 upd((data){0,g[i].bl,g[i].val-x*g[i].num}); 59 } 60 return 0; 61 } 62 int cheQ(ll x) 63 { 64 A=B=(data){0,0,inf};int j=pos; 65 dwn(i,pos-1,1) 66 { 67 for(;j<=len&&g[i].val+g[j].val<0;j++) upd((data){0,g[j].bl,(ll)x*g[j].num-g[j].val}); 68 if((A.bl==g[i].bl?B.val:A.val)<g[i].val-x*g[i].num) return 1; 69 upd((data){0,g[i].bl,(ll)x*g[i].num-g[i].val}); 70 } 71 return 0; 72 } 73 void calc(int x) 74 { 75 vis[x]=1,len=0;g[++len]=(data){0,0,0};ren if(!vis[to[i]]) Get(to[i],x,1,to[i],val[i]); 76 sort(g+1,g+len+1); 77 pos=lower_bound(g+1,g+len+1,(data){0,0,0})-g;ll l=1,r=ans; 78 for(ll mid;mid=l+r>>1,l<=r;) if(cheq(mid)||cheQ(-mid)) r=mid-1;else l=mid+1; 79 ans=min(ans,l-1); 80 } 81 void div(int x) 82 { 83 calc(x);ren if(!vis[to[i]]) Sum=sz[to[i]],Mx=n+1,getrt(to[i],x),div(rt); 84 } 85 int main() 86 { 87 n=read(),K=read();int a,b;ll c; 88 rep(i,2,n) a=read(),b=read(),c=read(),ans=min(ans,abs(c-K)),add(a,b,c-K),add(b,a,c-K); 89 Sum=n,Mx=n+1;getrt(1,0);div(rt);printf("%lld ",ans); 90 }
T3 定向越野(由于是计算几何所以咕咕咕了