测试 9
思路:一眼秒的水题,就是让你求Cnk
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 1000010 #define mod 1000000007 using namespace std; int f[MAXN]; int pow(int a,int b){ int ret=1%mod; while(b){ if(b&1) ret=ret*1LL*a%mod; b>>=1; a=a*1LL*a%mod; } return ret; } int ni(int x){ return pow(x,mod-2); } int C(int n,int m){ if(m>n) return 0; return f[n]*1LL*ni(f[m])%mod*ni(f[n-m])%mod; } int main(){ freopen("cube.in","r",stdin); freopen("cube.out","w",stdout); f[0]=1; int n,k; for(int i=1;i<=1000000;i++) f[i]=f[i-1]*1LL*i%mod; scanf("%d%d",&n,&k); for(int p,i=1;i<=n;i++) scanf("%d",&p); cout<<C(n,k); return 0; }
思路:跑一遍最大生成树。因为要达到最优的话,走的路径一定是最大生成树上的。
然后对于每次查询,二分答案去找小于k的数的个数。因为对于一棵树,有几条小于k的边,他就会被分割为k+1块。所以我们只要查询小于k的数的个数+1即为答案。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 100010 using namespace std; int n,m,q,w,num; int vis[MAXN],fa[MAXN],sum[MAXN]; struct nond{ int x,y,z; }edge[MAXN]; int cmp(nond a,nond b){ return a.z>b.z; } int find(int k){ if(fa[k]==k) return fa[k]; else return fa[k]=find(fa[k]); } int main(){ freopen("warehouse.in","r",stdin); freopen("warehouse.out","w",stdout); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z); sort(edge+1,edge+1+m,cmp); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++){ int dx=find(edge[i].x); int dy=find(edge[i].y); if(dx==dy) continue ; fa[dy]=dx; num++;sum[num]=edge[i].z; if(num==n-1) break; } sort(sum+1,sum+1+n-1); for(int i=1;i<=q;i++){ scanf("%d",&w); int l=1,r=n-1; while(l<=r){ int mid=(l+r)/2; if(sum[mid]<w) l=mid+1; else r=mid-1; } cout<<l<<endl; } return 0; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。