17-09-06模拟赛
T1:当横的切时,第i刀可以用直线y=b-√(i/n)*b表示。
竖着切时,考虑前((n-1)/2)刀,第i刀可以用直线y=√(i/2*n)*a表示。
当n为偶数时,第(n-1)/2+1刀可以用直线y=a/2表示。
后((n-1)/2)刀与前((n-1)/2)刀关于y=a/2对称。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 inline int in(){ 7 int x=0;bool f=0; char c; 8 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 9 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 10 return f?-x:x; 11 } 12 int n,a,b,c; 13 double p[1002]; 14 int main() 15 { 16 n=in();a=in();b=in();c=in(); 17 if (!c){ 18 for (int i=n-1;i;--i) 19 printf("%.10lf\n",(double)b-(double)(sqrt(i*1.0/n)*b)); 20 }else{ 21 for (int i=1;i<=(n-1)/2;++i) 22 p[i]=(double)a*(double)sqrt(i/(2.0*n)),printf("%.10lf\n",p[i]); 23 if (!(n&1)) printf("%.10lf\n",(double)a/2.0); 24 for (int i=(n-1)/2;i;--i) printf("%.10lf\n",(double)a-p[i]); 25 }return 0; 26 }
T2:二分k,对所有摊位物品此时的价格从小到大排序,枚举前k个物品的价格之和是否超过m。注意数据大小。时间复杂度O(n log2 n)
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 #define MN 100005 6 using namespace std; 7 inline int in(){ 8 int x=0;bool f=0; char c; 9 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 10 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 11 return f?-x:x; 12 } 13 int a[MN],b[MN],n,l,r,ans; 14 ll c[MN],m; 15 inline bool check(int k){ 16 if (!k) return 1;ll sum=0ll; 17 for (int i=1;i<=n;++i) c[i]=1ll*b[i]*(k-1)+a[i];sort(c+1,c+n+1); 18 for (int i=1;i<=k;++i) {sum+=c[i];if (sum>m) return 0;}return 1; 19 } 20 int main() 21 { 22 scanf("%d%lld",&n,&m); 23 for (int i=1;i<=n;++i) a[i]=in(),b[i]=in(); 24 l=0;r=n;while (l<=r){ 25 int mid=(l+r)>>1; 26 if (check(mid)) ans=mid,l=mid+1; 27 else r=mid-1; 28 }printf("%d",ans);return 0; 29 }
T3:考虑建立图论模型。
对bi的异或和求前缀和,从i向j连权值为sum[i]^sum[j]的边,表示由sum[i]求得sum[j]时所需要的话费为sum[i]^sum[j].
易知确定所有系数需要求出所有的sum值,所以对所有节点求最小生成树(MST)即可。
考虑到数据范围及图的特性,可以使用不加堆优化的Prim算法。时间复杂度为O(n2).
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define MN 10005 5 using namespace std; 6 inline int in(){ 7 int x=0;bool f=0; char c; 8 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 9 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 10 return f?-x:x; 11 } 12 int sum[MN],c[MN],n; 13 bool vis[MN]; 14 long long ans=0ll; 15 int main() 16 { 17 n=in();sum[0]=0; 18 for (int i=1;i<=n;++i) c[i]=sum[i]=sum[i-1]^in(); 19 for (int i=1;i<=n;++i){ 20 int v=0;for (int j=1;j<=n;++j) 21 if (!vis[j]&&(!v||c[j]<c[v])) v=j; 22 vis[v]=1;ans+=1ll*c[v]; 23 for (int j=1;j<=n;++j) c[j]=min(c[j],sum[j]^sum[v]); 24 }printf("%lld",ans);return 0; 25 }