Task 1
小 W 和小 M 一起玩拼图游戏啦~ 小 M 给小 M 一张 N 个点的图,有 M 条可选无向边,每条边有一个甜蜜值,小 W 要选 K条边,使得任意两点间最多有一条路径,并且选择的 K条边甜蜜值之和最大。
对于 100%的数据:N,M<=100000
最小生成树裸题
时间复杂度 O(nlogn)
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<algorithm> 4 #include<iostream> 5 #include<string> 6 #include<string.h> 7 #include<math.h> 8 #define il inline 9 #define re register 10 using namespace std; 11 const int N=1000001; 12 struct edge{int x,y,z; 13 } e[N]; 14 int n,m,k,f[N],ans=0,cnt=0; 15 il bool cmp(edge a,edge b){ 16 return a.z>b.z; 17 } 18 il int getfather(int u){ 19 if(!f[u]) return u; 20 return f[u]=getfather(f[u]); 21 } 22 int main(){ 23 freopen("carpet.in","r",stdin); 24 freopen("carpet.out","w",stdout); 25 scanf("%d%d%d",&n,&m,&k); 26 for(int i=1;i<=m;i++) 27 scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); 28 sort(e+1,e+m+1,cmp); 29 for(int i=1,fx,fy;i<=m;i++){ 30 fx=getfather(e[i].x); 31 fy=getfather(e[i].y); 32 if(fx==fy) continue; 33 f[fx]=fy; 34 ans+=e[i].z; 35 cnt++; 36 if(cnt==k) break; 37 } 38 cout<<ans; 39 return 0; 40 }
Task 2
小 W 顺利地完成了拼图,该他给小 M 出题啦。 小 W 定义“!”运算符:
1、 N!k = N!(k-1) * (N-1)!k (N> 0 aNd k > 0)
2、 N!k = 1 (N = 0)
3、 N!k = N (k = 0)
现在小 W 告诉小 M N 和 k,小 M 需要说出 N!k 的不同约数个数。 为了降低难度,答案对 1000000009 取模就好了。
对于 100%的数据:N<=1000,k<=100
对于每个质数求对答案的贡献
时间复杂度 O(n^2*m/ln(n))
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<algorithm> 4 #include<iostream> 5 #include<string> 6 #include<string.h> 7 #include<math.h> 8 #define il inline 9 #define re register 10 using namespace std; 11 int prime[10001],tot=0; 12 bool chk[10001]; 13 int n,m,f[1010][110]; 14 long long ans=1; 15 int main(){ 16 freopen("calc.in","r",stdin); 17 freopen("calc.out","w",stdout); 18 memset(chk,false,sizeof(chk)); 19 scanf("%d%d",&n,&m); 20 for(int i=2;i<=n;i++){ 21 if(!chk[i]){ 22 prime[++tot]=i; 23 for(int j=i+i;j<=n;j+=i) 24 chk[j]=true; 25 } 26 } 27 for(int k=1;k<=tot;k++){ 28 memset(f,false,sizeof(f)); 29 for(int i=1,j;i<=n;i++){ 30 f[i][0]=0;j=i; 31 while(j%prime[k]==0){ 32 j/=prime[k];f[i][0]++; 33 } 34 } 35 for(int i=1;i<=m;i++) f[0][i]=0; 36 for(int i=1;i<=n;i++) 37 for(int j=1;j<=m;j++){ 38 f[i][j]=f[i-1][j]+f[i][j-1]; 39 if(f[i][j]>1000000009) f[i][j]-=1000000009; 40 } 41 ans=ans*(1ll+f[n][m])%1000000009ll; 42 } 43 // cout<<clock()<<endl; 44 cout<<ans; 45 return 0; 46 }
Task 3
预处理只通过一个公司的线路,每个节点到其他节点的距离,暴力连边,跑最短路
时间复杂度O(cn^2logn)
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<algorithm> 4 #include<iostream> 5 #include<string> 6 #include<string.h> 7 #include<math.h> 8 #include<queue> 9 #define il inline 10 #define re register 11 using namespace std; 12 struct edge{int next,to,val; 13 } e[2000001]; 14 int n,m,c,s,t,M,p[100001],r[100001],q[100001],hs,h[100001]; 15 int d[100001],g[10001][101],v[100001],inq[100001]; 16 queue<int> que; 17 il void addedge(int x,int y,int z,int l){ 18 e[++M]=(edge){g[x][l],y,z};g[x][l]=M; 19 } 20 il void adde(int x,int y,int z){ 21 e[++M]=(edge){g[x][0],y,z};g[x][0]=M; 22 } 23 il void path(int h,int q){ 24 for(int i=1;i<=n;i++) d[i]=(1<<29); 25 d[h]=0;que.push(h); 26 while(!que.empty()){ 27 int h=que.front();que.pop();inq[h]=false; 28 for(int i=g[h][q];i;i=e[i].next){ 29 if(d[e[i].to]>d[h]+e[i].val){ 30 d[e[i].to]=d[h]+e[i].val; 31 if(!inq[e[i].to]){ 32 inq[e[i].to]=true; 33 que.push(e[i].to); 34 } 35 } 36 } 37 } 38 } 39 int main(){ 40 freopen("railway.in","r",stdin); 41 freopen("railway.out","w",stdout); 42 scanf("%d%d%d%d%d",&n,&m,&c,&s,&t); 43 for(int i=1,x,y,z,l;i<=m;i++){ 44 scanf("%d%d%d%d",&x,&y,&z,&l); 45 addedge(x,y,z,l); 46 addedge(y,x,z,l); 47 } 48 for(int i=1;i<=c;i++) 49 scanf("%d",&p[i]); 50 for(int i=1;i<=c;i++){ 51 for(int j=1;j<p[i];j++) 52 scanf("%d",&q[j]); 53 for(int j=1;j<=p[i];j++) 54 scanf("%d",&r[j]); 55 v[0]=0;q[0]=0; 56 for(int j=1;j<=p[i];j++) 57 v[j]=v[j-1]+(q[j]-q[j-1])*r[j]; 58 for(int j=1;j<=n;j++){ 59 path(j,i); 60 for(int k=1,l;k<=n;k++) if(k!=j&&d[k]<(1<<29)){ 61 l=lower_bound(q,q+p[i],d[k])-q-1; 62 adde(j,k,v[l]+(d[k]-q[l])*r[l+1]); 63 } 64 } 65 } 66 path(s,0); 67 if(d[t]<(1<<25)) cout<<d[t]<<endl; 68 else cout<<"-1"; 69 return 0; 70 }