牛客练习赛17

这次比赛的确比较水23333

A长方体

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给出共享长方体一个顶点的三个面的面积,求它十二条边的边长和。

输入描述:

一行三个整数a, b, c表示面积(1 <= a, b, c <= 10000)。

输出描述:

一行一个整数表示边长和。
示例1

输入

1 1 1

输出

12
示例2

输入

4 6 6

输出

28


设三边长为a、b、c,然后每个输入就是ab、bc、ac。先算出 $ abc= \sqrt{ab bc ac} $ 然后除一下就能得出a、b、c了。答案是(a+b+c)*4。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 #define pb push_back
 8 #define pbk pop_back
 9 #define ls(i) (i<<1)
10 #define rs(i) (i<<1|1)
11 #define mp make_pair
12 using namespace std;
13 LL a,b,c,l,ans;
14 int main()
15 {
16 
17     scanf("%lld%lld%lld",&a,&b,&c);
18     l=sqrt(a*b*c);
19     a=l/a;
20     b=l/b;
21     c=l/c;
22     ans=(a+b+c)*4;
23     printf("%lld\n",ans);
24     return 0;
25 }
View Code

 

B 好位置

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给出两个串s和x
定义s中的某一位i为好的位置,当且仅当存在s的子序列 满足y=x且存在j使得i=kj成立。
问s中是否所有的位置都是好的位置。

输入描述:

一行两个字符串s,x,这两个串均由小写字母构成。
1 <= |s|, |x| <= 200000

输出描述:

Yes表示是。
No表示不是。
示例1

输入

abab
ab

输出

Yes
示例2

输入

abacaba
aba

输出

No
示例3

输入

abc
ba

输出

No

把s去重并统计每位重复次数,去重后为ss,把x去重并统计每位重复次数,去重后为xx。然后串ss和串xx从头检查是不是每一位相等,在相等的情况下是不是重复次数ss的都比xx大。然后ss串和xx串从尾检查是不是每一位相等,在相等的情况下是不是重复次数ss的都比xx的大。然后再看看每一位的ss的字符是不是xx中都有。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 #define pb push_back
 8 #define pbk pop_back
 9 #define ls(i) (i<<1)
10 #define rs(i) (i<<1|1)
11 #define mp make_pair
12 using namespace std;
13 const int N=2e5+10;
14 char s[N],x[N];
15 bool vis[26];
16 int n,m,lens,lenx,lenss,lenxx;
17 char ss[N],xx[N];
18 int ns[N],nx[N];
19 int main()
20 {
21     scanf("%s%s",s,x);
22     lens=strlen(s);
23     lenx=strlen(x);
24     lenss=0;
25     lenxx=0;
26     clr(vis);
27     for(int i=0;i<lens;i++)
28     {
29         if(i>0)
30         {
31             if(s[i]==s[i-1])
32                 ns[lenss]++;
33             else
34             {
35                 ss[++lenss]=s[i];
36                 ns[lenss]=1;
37             }
38         }
39         else
40         {
41             ss[++lenss]=s[i];
42             ns[lenss]=1;
43         }
44     }
45     for(int i=0;i<lenx;i++)
46     {
47         if(i>0)
48         {
49             if(x[i]==x[i-1])
50                 nx[lenxx]++;
51             else
52             {
53                 xx[++lenxx]=x[i];
54                 nx[lenxx]=1;
55             }
56         }
57         else
58         {
59             xx[++lenxx]=x[i];
60             nx[lenxx]=1;
61         }
62     }
63     if(lenss<lenxx)
64     {
65         printf("No\n");
66         return 0;
67     }
68     for(int i=0;i<lenxx;i++)
69         if(ss[i]!=xx[i] || (ss[i]==xx[i] && ns[i]<nx[i]))
70         {
71             printf("No\n");
72             return 0;
73         }
74         else
75             vis[ss[i]-'a']=1;
76     for(int i=lenss-lenxx;i<lenss;i++)
77         if(ss[i]!=xx[i-(lenss-lenxx)] || (ss[i]==xx[i-(lenss-lenxx)] && ns[i]<nx[i-(lenss-lenxx)]))
78         {
79             printf("No\n");
80             return 0;
81         }
82     for(int i=0;i<lenss;i++)
83         if(!vis[ss[i]-'a'])
84         {
85             printf("No\n");
86             return 0;
87         }
88     printf("Yes\n");
89     return 0;
90 }
View Code

 

C 操作数

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给定长度为n的数组a,定义一次操作为:
1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007;
2. 执行a = s;
现在问k次操作以后a长什么样。

输入描述:

第一行两个整数n,k(1 <= n <= 2000, 0 <= k <= 1,000,000,000);
第二行n个整数表示a数组(0 <= a
i
<= 1,000,000,000)。

输出描述:

一行n个整数表示答案。
示例1

输入

3 1
1 2 3

输出

1 3 6
示例2

输入

5 0
3 14 15 92 6

输出

3 14 15 92 6

 

加和类的问题肯定是和组合数有关系的啦。

首先是

$ \begin{bmatrix} a_1 & a_2 & a_3 & ……& a_n \end{bmatrix}\quad $ $ \begin{bmatrix}1 & 1 & 1 &  …… & 1 \\ 0 & 1 & 1 &  …… & 1 \\ 0 & 0 & 1 &  …… & 1 \\  …… & …… & …… &  …… & …… \\ 0 & 0 & 0 &  …… & 1 \end{bmatrix}^{k-1} \quad  $

然后你求后面这个矩阵k-1次方以后会发现其实他是:

 $ \begin{bmatrix} C^0_{k-1} & C^1_{k} &  C^2_{k+1} &  …… &  C^{n-1}_{k+n-2} \\ 0 & C^0_{k-1} &  C^1_{k} & …… &  C^{n-2}_{k+n-3}  \\  …… & …… & …… &  …… & …… \\ 0 & 0 & 0 &  …… & C^0_{k-1} \end{bmatrix} \quad  $

然后写个快速幂求一下逆元,然后求一下对应的组合数就好了。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 #define pb push_back
 8 #define pbk pop_back
 9 #define ls(i) (i<<1)
10 #define rs(i) (i<<1|1)
11 #define mp make_pair
12 using namespace std;
13 const int N=1e4+10;
14 LL fac[N],inv[N];
15 LL quick_pow(LL x,LL n)
16 {
17     LL res=1;
18     x%=mod;
19     while(n)
20     {
21         if(n&1) res=res*x%mod;
22         n>>=1,x=x*x%mod;
23     }
24     return res;
25 }
26 LL k,a[N],mul[N],ans[N];
27 int n;
28 void init(int n,LL k)
29 {
30     fac[0]=1;
31     LL p=1;
32     for(int i=1;i<=n;i++)
33         fac[i]=fac[i-1]*(i+k)%mod,p=p*i%mod;
34 
35     inv[n]=quick_pow(p,mod-2);
36     for(int i=n-1;i>=0;i--)
37         inv[i]=inv[i+1]*(i+1)%mod;
38     return ;
39 }
40 LL comb(int n)
41 {
42     return fac[n]*inv[n]%mod;
43 }
44 int main()
45 {
46     scanf("%d%lld",&n,&k);
47     for(int i=1;i<=n;i++)
48         scanf("%lld",a+i);
49     init(n,k-1);
50     for(int i=0;i<=n;i++)
51         mul[i]=comb(i);
52     for(int i=1;i<=n;i++)
53     {
54         for(int j=0;j<i;j++)
55         {
56             int k=i-j;
57             ans[i]=(ans[i]+a[k]*mul[j]%mod)%mod;
58         }
59     }
60     for(int i=1;i<n;i++)
61         printf("%lld ",ans[i]);
62     printf("%lld\n",ans[n]);
63     return 0;
64 }
View Code

 

D 经纬度

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给定地球的两个经纬度坐标,问这两个点的球面距离和直线距离的差。假设地球为球体,半径为6371009米。

输入描述:

第一行一个整数T表示数据组数。
接下来n行,每行四个数lat1, lng1, lat2, lng2分别表示两个点的经纬度。
正数表示北纬和东经。
负数表示南纬和西经。
数据保证合法。

输出描述:

n行表示答案。
答案保留到米。
示例1

输入

1
43.466667 -80.516667 30.058056 31.228889

输出

802333

数学公式题233。

我不会,baidu found search bfs一下就能找到球面公式然后改改。

你也可以拿球面的公式去推。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 #define pb push_back
 8 #define pbk pop_back
 9 #define ls(i) (i<<1)
10 #define rs(i) (i<<1|1)
11 #define mp make_pair
12 using namespace std;
13 const int N=1e4+10;
14 const double r=6371009;
15 const double PI=3.1415926535;
16 double ax,ay,bx,by;
17 double d1,d2,subx,suby,t,cos1,cos2;
18 double linlen,ballen;
19 int T;
20 int main()
21 {
22     scanf("%d",&T);
23     while(T--)
24     {
25         scanf("%lf%lf%lf%lf",&ax,&ay,&bx,&by);
26         ax=ax*PI/180;
27         bx=bx*PI/180;
28         ay=ay*PI/180;
29         by=by*PI/180;
30         //球面距离公式
31         linlen=r*sqrt(2-2*(cos(ax)*cos(bx)*cos(ay-by)+sin(ax)*sin(bx)));
32         //球面直线距离公式
33         ballen=2*asin(linlen/(2*r))*r;
34         printf("%.0f\n",ballen-linlen);
35     }
36     return 0;
37 }
View Code

 

E 求长度

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

给定一幅n个点m条边的图和S个一定要经过的点,问从0号点出发,经过这S个点再回到0号点的最短路径长度是多少。

输入描述:

第一行一个整数T(T <= 2)表示数据组数。
对于每组数据,第一行两个整数n,m表示点数和边数(1 <= n, m <= 100,000)。
接下来m行,每行三个整数x, y, z(0 < x, y < n, 0 <= z <= 1000)表示xy之间有一条长度为c的双向边;
接下来一个整数S。(S<=10)
接下来S行每行一个整数表示一定要经过的点。
数据保证有解。

输出描述:

T行,每行一个整数表示答案。
示例1

输入

1
4 6
0 1 1
1 2 1
2 3 1
3 0 1
0 2 5
1 3 5
3
1
2
3

输出

4

先拿0号点和所有要经过的点把他们互相的最短距离算出来,然后建一个新图包含这些点以及他们最短距离。然后拿排列(你也可以dfs+标记)枚举所有可能出现的走法。取走法里长度最小的那个。

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define clrmax(x) memset(x,0x3f3f3f3f,sizeof(x))
  5 #define mod 1000000007
  6 #define INF 0x3f3f3f3f
  7 #define LL long long
  8 #define pb push_back
  9 #define pbk pop_back
 10 #define ls(i) (i<<1)
 11 #define rs(i) (i<<1|1)
 12 #define mp make_pair
 13 using namespace std;
 14 const int N=1e5+10;
 15 typedef pair<int,int> par;
 16 int d[N];
 17 struct edg
 18 {
 19     int from,to,next,val;
 20 }edge[N<<2];
 21 int head[N],etot;
 22 void init(int n)
 23 {
 24     for(int i=0;i<n;i++)
 25         head[i]=-1;
 26     etot=0;
 27 }
 28 void addedge(int u,int v,int val)
 29 {
 30     edge[++etot]=(edg){u,v,head[u],val};
 31     head[u]=etot;
 32     return ;
 33 }
 34 struct prt
 35 {
 36     int pt,val;
 37     bool operator <(const prt & t) const
 38     {
 39         return val<t.val;
 40     }
 41 };
 42 int dtp[20][20];
 43 int s[20];
 44 int per[20];
 45 int T,n,m,u,v,val,snum,p;
 46 par pp;
 47 int ans=0;
 48 priority_queue<par,vector<par>,greater<par> > que;
 49 int main()
 50 {
 51     scanf("%d",&T);
 52     while(T--)
 53     {
 54         scanf("%d%d",&n,&m);
 55         init(n);
 56         for(int i=1;i<=m;i++)
 57         {
 58             scanf("%d%d%d",&u,&v,&val);
 59             addedge(u,v,val);
 60             addedge(v,u,val);
 61         }
 62         scanf("%d",&snum);
 63         for(int i=1;i<=snum;i++)
 64             scanf("%d",s+i);
 65         s[0]=0;
 66         s[snum+1]=0;
 67         sort(s,s+snum+1);
 68         snum=unique(s,s+snum+1)-s-1;
 69         for(int i=0;i<=snum;i++)
 70             per[i]=i;
 71         per[snum+1]=0;
 72         for(int i=0;i<=snum;i++)
 73         {
 74             for(int j=0;j<n;j++)
 75                 d[j]=INF;
 76             d[s[i]]=0;
 77             que.push(par(0,s[i]));
 78             while(!que.empty())
 79             {
 80                 pp=que.top();
 81                 que.pop();
 82                 v=pp.second;
 83                 for(int j=head[v];j!=-1;j=edge[j].next)
 84                 {
 85                     p=edge[j].to;
 86                     if(d[p]>d[v]+edge[j].val)
 87                     {
 88                         d[p]=d[v]+edge[j].val;
 89                         que.push(par(d[p],p));
 90                     }
 91                 }
 92             }
 93             for(int j=0;j<=snum;j++)
 94                 dtp[i][j]=d[s[j]];
 95         }
 96         ans=INF;
 97         do
 98         {
 99             val=0;
100             for(int i=0;i<=snum;i++)
101                 val+=dtp[per[i]][per[i+1]];
102             ans=min(ans,val);
103         }
104         while(next_permutation(per+1,per+snum+1));
105         printf("%d\n",ans);
106     }
107     return 0;
108 }
View Code

 

F 玩游戏

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给定两个串S和T,|S| >= |T|。
alice和bob轮流操作串S,bob先手。
对于每次操作,alice或bob会选择删掉S的第一位或最后一位。
当操作以后的串的长度等于|T|时,游戏停止。
如果停止时的串=T,则alice获胜,否则bob获胜。
问在alice和bob均采取最优策略的情况下,谁赢?

输入描述:

第一行一个整数T(T <= 1000)表示数据组数。
接下来T行每行两个整数字符串S, T。 (1 <= |S| <= |T| <= 500000,S和T均由小写字母构成)
字符串总长度 <= 1000000

输出描述:

T行。
对于每组数据,alice赢输出'Alice', bob赢输出'Bob'。
示例1

输入

5
aba b
bab b
aaab aab
xyz mnk
xyz xyz

输出

Alice
Alice
Bob
Bob
Alice

双方都可以模仿对方的行动,做出对称的行动来达到自己的目的。
先讨论他们字符串长度差为偶数的情况。
对于一个x在s的正中央,alice可以通过模仿bob的对称行动达到自己获胜的局面。
对于x不在正中央,但是却在中央位置-1处和+1处各有一个x的情况,alice可以在bob去除完一次以后再同侧再去除一次,然后模仿bob的对称行动达到自己获胜的局面。
最多只能在同侧多删俩,因为bob很聪明如果你在同侧删了的话他可以去另一侧删的。
然后奇数的情况就相当于偶数时x不在正中央的情况,如果有那样两串的话就alice赢。
其他情况bob赢。
可以看出结果就两种情况,留下中央串或者中央偏左或偏右一串。这是他们最优策略将会导致的结果。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define clrmax(x) memset(x,0x3f3f3f3f,sizeof(x))
 5 #define mod 1000000007
 6 #define INF 0x3f3f3f3f
 7 #define LL long long
 8 #define pb push_back
 9 #define pbk pop_back
10 #define ls(i) (i<<1)
11 #define rs(i) (i<<1|1)
12 #define mp make_pair
13 using namespace std;
14 const int N=5e5+10;
15 string s1,s2,sb1,sb2,sb3;
16 int len1,len2,hd,T;
17 int main()
18 {
19     scanf("%d",&T);
20     while(T--)
21     {
22        cin>>s1>>s2;
23        len1=s1.size();
24        len2=s2.size();
25        hd=(len1-len2);
26        if(len1<=len2)
27        {
28            if(s1==s2) printf("Alice\n");
29            else printf("Bob\n");
30            continue;
31        }
32        if(hd%2==0)
33        {
34            sb1=s1.substr((len1-len2)/2-1,len2);
35            sb2=s1.substr((len1-len2)/2,len2);
36            sb3=s1.substr((len1-len2)/2+1,len2);
37            if((sb1==sb3 && sb1==s2) || sb2==s2)
38            {
39                printf("Alice\n");
40                continue;
41            }
42        }
43        if(hd%2==1)
44        {
45            sb2=s1.substr((len1-len2)/2,len2);
46            sb3=s1.substr((len1-len2)/2+1,len2);
47            if(sb2==s2 && sb3==s2)
48            {
49                printf("Alice\n");
50                continue;
51            }
52        }
53        printf("Bob\n");
54        continue;
55     }
56     return 0;
57 }
View Code

 

posted @ 2018-05-07 19:49  hk_lin  阅读(689)  评论(0编辑  收藏  举报