TZOJ 挑战题库随机训练07

点击题号跳转

A4586 B3342 C6104 D2013 E1752

F4708 G3604 H6148 I1433 J1861

A.最小二乘法回到顶部

题意

给个函数,求偏导

题解

高等数学题,过程就不列了,计算可得,复杂度O(1)

k=(Σ(xy)-ΣxΣy/n)/(-(Σx)^2/n+Σ(x^2))

b=(Σy-kΣx)/n

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int n;
 6     while(scanf("%d",&n)!=EOF){
 7         double sumx=0,sumx2=0,sumy=0,sumxy=0,x,y;
 8         for(int i=1;i<=n;i++){
 9             scanf("%lf%lf",&x,&y);
10             sumx+=x,sumy+=y,sumxy+=x*y,sumx2+=x*x;
11         }
12         double k=(sumxy-sumx*sumy/n)/(-sumx*sumx/n+sumx2);
13         double b=(sumy-k*sumx)/n;
14         printf("%.1f %.1f\n",k,b);
15     }
16     return 0;
17 }
A

B.Children’s Queue回到顶部

题意

长度为n的序列放0和1,所有的1必须有相邻的1,问方案数,n<=1000

题解

dp[i]表示长度为i的合法方案数

第i个位置放0,那么前i-1个无所谓,dp[i-1]

第i个位置放1,因为要连续,i-1和i-2都放1,dp[i-2]

其实还有一种情况,第i个位置放1,如果前面不合法,放两个1也会导致合法,那么就相当于第i-3放0,i-2放1,相当于不合法,然后放两个连续的1使其合法,就相当于放0111,dp[i-4]

dp[i]=dp[i-1]+dp[i-2]+dp[i-4],复杂度O(1000)

代码

 1 import java.math.BigInteger;
 2 import java.util.*;
 3 
 4 public class Main {
 5 
 6     public static void main(String[] args) {
 7 
 8         BigInteger[] big = new BigInteger[1005];
 9         big[0] = BigInteger.ONE;
10         big[1] = BigInteger.ONE;
11         big[2] = big[0].add(big[1]);
12         big[3] = big[2].add(big[0].add(big[1]));
13         for(int i = 4; i <= 1000; i++) {
14             big[i] = big[i-1].add(big[i-2].add(big[i-4]));
15         }
16         Scanner sc = new Scanner(System.in);
17         while(sc.hasNext()) {
18             int n = sc.nextInt();
19             System.out.println(big[n]);
20         }
21     }
22 }
B

C.Island Transport回到顶部

题意

一张图(u,v,w),从左下开始,到右上,w表示容量,问最多能运多少,N,M<=100000

题解

一看就是网络流,但是N,M这么大怎么办?莽呗,复杂度O(你的模板复杂度)

代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<queue>
  6 #define INF 0x3f3f3f3f
  7 using namespace std;
  8 const int maxn=100005;
  9 const int maxx=200005;
 10 int edge;
 11 int to[maxx],flow[maxx],nex[maxx];
 12 int head[maxn];
 13 
 14 void addEdge(int v,int u,int cap)
 15 {
 16     to[edge]=u,flow[edge]=cap,nex[edge]=head[v],head[v]=edge++;
 17     to[edge]=v,flow[edge]=cap,nex[edge]=head[u],head[u]=edge++;
 18 }
 19 int vis[maxn];
 20 int pre[maxn];
 21 bool bfs(int s,int e)
 22 {
 23     queue<int> que;
 24     pre[s]=-1;
 25     memset(vis,-1,sizeof(vis));
 26     que.push(s);
 27     vis[s]=0;
 28     while(!que.empty())
 29     {
 30         int u=que.front();
 31         que.pop();
 32         for(int i=head[u];~i;i=nex[i])
 33         {
 34             int v=to[i];
 35             if(vis[v]==-1&&flow[i])
 36             {
 37                 vis[v]=vis[u]+1;
 38                 if(v==e)
 39                     return true;
 40                 que.push(v);
 41             }
 42 
 43         }
 44     }
 45     return false;
 46 }
 47 int dfs(int s,int t,int f)
 48 {
 49     if(s==t||!f)
 50         return f;
 51     int r=0;
 52     for(int i=head[s];~i;i=nex[i])
 53     {
 54         int v=to[i];
 55         if(vis[v]==vis[s]+1&&flow[i])
 56         {
 57             int d=dfs(v,t,min(f,flow[i]));
 58             if(d>0)
 59             {
 60                 flow[i]-=d;
 61                 flow[i^1]+=d;
 62                 r+=d;
 63                 f-=d;
 64                 if(!f)
 65                     break;
 66             }
 67         }
 68     }
 69     if(!r)
 70         vis[s]=INF;
 71     return r;
 72 }
 73 
 74 int maxFlow(int s,int e)
 75 {
 76     int ans=0;
 77     while(bfs(s,e))
 78         ans+=dfs(s,e,INF);
 79     return ans;
 80 }
 81 
 82 void init()
 83 {
 84     memset(head,-1,sizeof(head));
 85     edge=0;
 86 }
 87 
 88 int main(){
 89     int t,x,y,w,n,m,s,e,maxI,minI;
 90     scanf("%d",&t);
 91     while(t--){
 92         init();
 93         scanf("%d%d%d%d",&n,&m,&x,&y);
 94         s=e=1;
 95         maxI=minI=x;
 96         for(int i=2;i<=n;i++){
 97             scanf("%d%d",&x,&y);
 98             if(maxI<x)e=i,maxI=x;
 99             if(minI>x)s=i,minI=x;
100         }
101         while(m--){
102             scanf("%d%d%d",&x,&y,&w);
103             addEdge(x,y,w);
104         }
105         int ans=maxFlow(s,e);
106         printf("%d\n",ans);
107     }
108     return 0;
109 }
C

D.Problem Bee回到顶部

题意

给俩坐标A和B,蜂巢正六边形,给你个边长d,A要移动到B,如果AB在同一蜂巢直接移动过去,如果在不同蜂巢,A需要移动到中心,每次只能移动到相邻蜂巢,到达B蜂巢中心后再移动到B,蜂巢总中心在(0,0)

题解

数学题,先算出A和B在哪个蜂巢,再计算出需要移动几个蜂巢,最后加上A到中心和B到中心的距离

通过计算可得,x变化量为3d/2,y变化量为sqrt(3)d/2,算出A处在x的第几块,通过奇偶算出A处在y的第几块,然后计算周围的6个蜂巢得到A到底在哪个蜂巢中

同理计算出B,复杂度O(1)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int dx[]={0,0,1,1,-1,-1};
 4 int dy[]={2,-2,1,-1,1,-1};
 5 double d;
 6 void changes(double realx,double realy,double &x1,double &y1){
 7     double minn=(x1-realx)*(x1-realx)+(y1-realy)*(y1-realy);
 8     double truex=x1,truey=y1;
 9     for(int i=0;i<6;i++){
10         double rx1=x1+dx[i]*(3*d/2);
11         double ry1=y1+dy[i]*(sqrt(3.0)*d)/2;
12         double val=(rx1-realx)*(rx1-realx)+(ry1-realy)*(ry1-realy);
13         //if(i==3)printf("%.3f %.3f %.3f\n",rx1,ry1,val);
14         if(val<minn){
15             minn=val;
16             truex=rx1,truey=ry1;
17         }
18     }
19     x1=truex,y1=truey;
20 }
21 int main(){
22     double x1,y1,x2,y2;
23     while(scanf("%lf%lf%lf%lf%lf",&d,&x1,&y1,&x2,&y2)!=EOF){
24         //printf("%.3f %.3f %.3f %.3f %.3f\n",d,x1,y1,x2,y2);
25         if(x1==0&&y1==0&&x2==0&&y2==0)break;
26         int b1=x1*2/(3*d),b2=x2*2/(3*d);
27         int e1=y1*2/(d*sqrt(3.0)),e2=y2*2/(d*sqrt(3.0));
28         if(b1%2==1&&e1%2==0)e1++;
29         else if(b1%2==0&&e1%2==1)e1++;
30         if(b2%2==1&&e2%2==0)e2++;
31         else if(b2%2==0&&e2%2==1)e2++;
32         //printf("%d %d %d %d\n",b1,b2,e1,e2);
33         if(b1==b2&&e1==e2){
34             printf("%.3f\n",sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)));
35         }else{
36             double b1x=b1*3*d/2;
37             double b2x=b2*3*d/2;
38             double b1y=e1*sqrt(3.0)*d/2;
39             double b2y=e2*sqrt(3.0)*d/2;
40             changes(x1,y1,b1x,b1y);
41             changes(x2,y2,b2x,b2y);
42             //(b1x,b1y)->(b2x,b2y)
43             //printf("(%.3f,%.3f) (%.3f,%.3f)\n",b1x,b1y,b2x,b2y);
44             int move=fabs(b2x-b1x)*2/(3*d);
45             printf("%.3f\n",move*d*sqrt(3.0)+sqrt((x1-b1x)*(x1-b1x)+(y1-b1y)*(y1-b1y))+sqrt((x2-b2x)*(x2-b2x)+(y2-b2y)*(y2-b2y)));
46         }
47     }
48     return 0;
49 }
D

E.Tree Recovery回到顶部

题意

给前序中序求后序,n<30

题解

递归建树,dfs(L1,R1,L2,R2)代表前序中的[L1,R1],中序中的[L2,R2]

前序第一个数一定是根,然后在中序中找到根的下标,左右两半分开,复杂度O(n)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n;
 5 char s1[30],s2[30];
 6 int dfs(int L1,int R1,int L2,int R2){
 7     if(L1>R1)return 0;
 8     char root=s1[L1];int p=L2;
 9     while(root!=s2[p])p++;
10     int cnt=p-L2;
11     dfs(L1+1,L1+cnt,L2,p-1);
12     dfs(L1+cnt+1,R1,p+1,R2);
13     printf("%c",root);
14     return root;
15 }
16 int main(){
17     while(scanf("%s%s",s1,s2)!=EOF){
18         n=strlen(s1);
19         dfs(0,n-1,0,n-1);
20         printf("\n");
21     }
22     return 0;
23 }
E

F.小孩子的扑克牌游戏回到顶部

题意

A和B各有两张扑克,问谁的和离10最近,相同和大的赢

题解

求和判一下绝对值,复杂度O(1)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int a,b,c,d;
 6     while(cin>>a>>b>>c>>d){
 7         int e=abs(10-a-b);
 8         int f=abs(10-c-d);
 9         if(e==f&&a+b==c+d)cout<<"2 2\n";
10         else if(e<f||a+b<c+d)cout<<"4 0\n";
11         else cout<<"0 4\n";
12     }
13     return 0;
14 }
F

G.The Table回到顶部

题意

n行m列,问哪一列乘积最大,相同输出m大的,n<=1000,m<=20

题解

大数相乘处理一下就行了,复杂度O(nm)

代码

 1 import java.math.BigInteger;
 2 import java.util.*;
 3 
 4 public class Main {
 5 
 6     public static void main(String[] args) {
 7 
 8         BigInteger[] big = new BigInteger[25];
 9 
10         Scanner sc = new Scanner(System.in);
11         while(sc.hasNext()) {
12             int m = sc.nextInt();
13             int n = sc.nextInt();
14             BigInteger b;
15             for (int i = 1; i <= m; i++)
16                 big[i] = BigInteger.ONE;
17             for (int i = 1; i <= n; i++) {
18                 for (int j = 1; j <= m; j++) {
19                     b = sc.nextBigInteger();
20                     big[j] = big[j].multiply(b);
21                 }
22             }
23             int id = 1;
24             BigInteger maxx = big[1];
25             for (int i = 2; i <= m; i++) {
26                 if (maxx.compareTo(big[i]) <= 0) {
27                     maxx = big[i];
28                     id = i;
29                 }
30             }
31             System.out.println(id);
32         }
33     }
34 }
G

H.求和回到顶部

题意

矩阵求和,除去最后一列,最后一行,副对角线,n<=100

题解

两个for,判一下i=n-1,j=n-1,i=n-j+1,复杂度O(n^2)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int n,x;
 6     while(cin>>n){
 7         int sum=0;
 8         for(int i=1;i<=n;i++)
 9             for(int j=1;j<=n;j++){
10                 cin>>x;
11                 if(i==n||j==n||i==n-j+1)continue;
12                 sum+=x;
13             }
14         cout<<sum<<'\n';
15     }
16     return 0;
17 }
H

I.正整数解回到顶部

题意

计算方程x^2+y^2+z^2=num的最小正整数解,num<=10000

题解

100^2=10000,那么直接三个for,复杂度O(<<100^3)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int num,x,y,z;
 6     e:while(cin>>num){
 7         for(int i=1;i<=num;i++){
 8             if(i*i>num)break;
 9             for(int j=i;j<=num;j++){
10                 if(i*i+j*j>num)break;
11                 for(int k=j;k<=num;k++){
12                     if(i*i+j*j+k*k>num)break;
13                     if(i*i+j*j+k*k==num){
14                         cout<<i<<" "<<j<<" "<<k<<'\n';
15                         goto e;
16                     }
17                 }
18             }
19         }
20     }
21     return 0;
22 }
I

J.Perfect Cubes回到顶部

题意

函数a^3+b^3+c^3=n,求<=n的所有解,n<=100

题解

4个for,10^2=100,复杂度O(n*10^3)

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int n,x;
 6     while(scanf("%d",&n)!=EOF){
 7         for(int i=6;i<=n;i++){
 8             for(int j=2;j<=n;j++){
 9                 if(i*i*i<j*j*j)break;
10                 for(int k=j;k<=n;k++){
11                     if(i*i*i<j*j*j+k*k*k)break;
12                     for(int l=k;l<=n;l++){
13                         if(i*i*i<j*j*j+k*k*k+l*l*l)break;
14                         if(i*i*i==j*j*j+k*k*k+l*l*l){
15                             printf("Cube = %d, Triple = (%d,%d,%d)\n",i,j,k,l);
16                         }
17                     }
18                 }
19             }
20         }
21     }
22     return 0;
23 }
J

posted on 2020-04-04 11:08  大桃桃  阅读(495)  评论(0编辑  收藏  举报

导航