今天又是模拟赛,明天就去听讲座了。
Test:0 最小花费
jzoj2125
(题目:在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。)
先预处理一下节点之间的权值,再跑最短路(建议用迪杰斯特拉,spfa可能会被数据卡。);
code:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int w,n,m,x,y,h,p[2005],k[2005]; double v,maxn,b[2005]; struct rect { int to,next; double l; }a[4000005]; int main() { freopen("money.in", "r", stdin) freopen("money.out", "w", stdout); scanf("%d %d",&n,&m); for (int i = 1;i <= m;++i) { scanf("%d %d %lf",&x,&y,&v); a[++w].to = y; a[w].l = (100-v)/100; a[w].next = k[x]; k[x] = w; a[++w].to = x; a[w].l =(100-v)/100; a[w].next = k[y]; k[y] = w; } scanf("%d %d",&x,&y); for (int i = k[x];i;i = a[i].next) { b[a[i].to] = a[i].l; } p[x] = 1; b[x] = 1; for (int i = 2;i < n;++i) { maxn = 0; h = 0; for (int j = 1;j <= n;++j) { if (!p[j]&&b[j] > maxn) { maxn = b[j]; h = j; } } if (!h) { break; } p[h] = 1; for (int i = k[h];i;i = a[i].next) { if (!p[a[i].to]&&b[h]*a[i].l > b[a[i].to]) { b[a[i].to] = b[h]*a[i].l; } } } printf("%.8lf",100/b[y]); return 0; }
Test:1 最大约数和
jzoj2126
(题目:选取和不超过S(是<=1000)的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大。)
简单,最优解用dp,先用一个sum数组储存s以前的数的因数和,再做01背包(sum[i]相当于价值,数字相当于重量,s相当于容量);
code:
#include<cstdio> #include<iostream> #include<cmath> using namespace std; int s; int f[1000100]; int sum[1000100]; int main() { freopen("maxsum.in", "r", stdin); freopen("maxsum.out", "w", stdout); scanf("%d",&s); for(int i = 2;i <= s;++i)//2-s分解因数 { for(int j = 1;j <= i-1;++j) { if(i % j==0) { sum[i]+=j;//求因数的和 } } } for(int i = 1;i <= s;++i)//0 1背包 { for(int j = s;j >= i;--j) { f[j] = max(f[j],f[j-i]+sum[i]); } } printf("%d",f[s]);//输出最优解 return 0; }
Test:2 电子表格
jzoj2127
(题目:太长不想写,一眼看上去像是二维的线段树,但其实直接暴力就可以过。有四种操作:1.赋值 2.输出 3.将一个矩形区域的平均值赋值在一个数上 4.将一个矩形区域的和赋值在一个数上)
code:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int a[200][52],in,m,n,s,wcs,w1s,w2s,jlsum[200][52][4],jlavg[200][52][4]; char wc,c[20],w1c,w2c; bool sf[200][52],sf1[200][52]; int jsavg(int,int); int jssum(int ax,int ay) { if(jlsum[ax][ay][0]==-1 && jlavg[ax][ay][0]==-1) { sf[ax][ay]=1; return a[ax][ay]; } // sf[ax][ay]=1; int all=0; for(int i=jlsum[ax][ay][0];i<=jlsum[ax][ay][2];i++) for(int j=jlsum[ax][ay][1];j<=jlsum[ax][ay][3];j++) { if(jlsum[i][j][0]!=-1) all+=jssum(i,j); else if(jlavg[i][j][0]!=-1) all+=jsavg(i,j); else all+=a[i][j]; } a[ax][ay]=all; return all; } int jsavg(int ax,int ay) { if(jlavg[ax][ay][0]==-1 && jlsum[ax][ay][0]==-1) { sf[ax][ay]=1; return a[ax][ay]; } // sf[ax][ay]=1; int all=0; for(int i=jlavg[ax][ay][0];i<=jlavg[ax][ay][2];i++) for(int j=jlavg[ax][ay][1];j<=jlavg[ax][ay][3];j++) { if(jlsum[i][j][0]!=-1) all+=jssum(i,j); else if(jlavg[i][j][0]!=-1) all+=jsavg(i,j); else all+=a[i][j]; } a[ax][ay]=all/((jlavg[ax][ay][2]-jlavg[ax][ay][0]+1)*(jlavg[ax][ay][3]-jlavg[ax][ay][1]+1)); return a[ax][ay]; } int main() { freopen("excel.in","r",stdin); freopen("excel.out","w",stdout); cin>>m>>n>>s; memset(jlsum,-1,sizeof(jlsum)); memset(jlavg,-1,sizeof(jlavg)); while(s--) { cin>>wc; cin>>wcs>>c; int x=wcs,y=wc-'A'+1; if(c[0]=='i') { cin>>in; a[x][y]=in; for(int i=0;i<4;i++) jlsum[x][y][i]=-1,jlavg[x][y][i]=-1; // memset(sf,0,sizeof(sf)); // memset(sf1,0,sizeof(sf1)); // for(int i=1;i<=n;i++) // for(int j=1;j<=m;j++) // { // // } } else if(c[0]=='o') { if(jlsum[x][y][0]!=-1) jssum(x,y); else if(jlavg[x][y][0]!=-1) jsavg(x,y); cout<<a[x][y]<<endl; } else if(c[0]=='s') { cin>>w1c>>w1s>>w2c>>w2s; // int all=0; // memset(sf,0,sizeof(sf)); // memset(sf1,0,sizeof(sf1)); jlsum[x][y][0]=w1s; jlsum[x][y][1]=w1c-'A'+1; jlsum[x][y][2]=w2s; jlsum[x][y][3]=w2c-'A'+1; for(int i=0;i<4;i++) jlavg[x][y][i]=-1; // jssum(x,y); // a[wcs][wc-'A'+1]=all; } else if(c[0]=='a') { cin>>w1c>>w1s>>w2c>>w2s; // int all=0; // memset(sf,0,sizeof(sf)); // memset(sf1,0,sizeof(sf1)); // a[wcs][wc-'A'+1]=all/((w2s-w1s+1)*(w2c-w1c+1)); jlavg[x][y][0]=w1s; jlavg[x][y][1]=w1c-'A'+1; jlavg[x][y][2]=w2s; jlavg[x][y][3]=w2c-'A'+1; for(int i=0;i<4;i++) jlsum[x][y][i]=-1; // jsavg(x,y); } } return 0; }
Test:3 X-因子链
jzoj2128
首先我们将x 分解质因数
比如100=2^2*5^2
然后我们用a 数组装下这些质数的次方
第一的答案tot既为 a 数组的和 既2+2=4
第二个答案用排列组合
用tot的阶乘除(a[i]!*…a[m](a[i]<>0) 的阶乘)
也就是4!/(2!*2!)
既为第二个答案
同时注意将1至20的阶乘全部求出来,方便直接调用。(题解)
code:
#include <cstdio> #include <cctype> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; int main() { freopen("factor.in","r",stdin); freopen("factor.out","w",stdout); ll x[25] = {1}; for(ll i = 1;i < 25;++i) { x[i] = i * x[i - 1]; } ll n; scanf("%lld",&n); ll ans = 0,base = 1; for(ll i = 2;i * i <= n;++i) { if(n % i == 0) { ll cnt = 0; while(n % i == 0) { ++cnt; n /= i; } ans += cnt; base *= x[cnt]; } } if(n > 1) { ans += 1; } printf("%lld %lld",ans,x[ans] / base); return 0; }
今天的题其实还挺简单的(前两题),so, 100|400分,rank 8 。