牛客练习赛17

 

 A.
链接: https://www.nowcoder.com/acm/contest/109/A
来源:牛客网

题目描述

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

输入描述:

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

输出描述:

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

输入

1 1 1

输出

12
示例2

输入

4 6 6

输出

28

设三边长度为A,B,C,则有a=AB,b=BC,c=AC,枚举一下B如果满足B是a和b的因子且能满足c=AC,就直接计算输出结果。
    
 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include<set>
 7 #include
 8 #include
 9 #include
10 #include 
11 #include
12 using namespace std;
13 #define mp make_pair
14 #define pb push_back
15 #define debug puts("debug")
16 #define LL long long 
17 #define pii pair
18 #define eps 1e-10
19 int gcd(int a,int b){
20     return b==0?a:gcd(b,a%b);
21 }
22 int main()
23 {
24     int n,m,i,j,k;
25     LL a,b,c;
26     LL A,B,C;
27     cin>>a>>b>>c;
28     n=max(a,b);
29     for(B=1;B<=n;++B){
30         if(a%B==0&&b%B==0){
31             if(c==a/B*b/B){
32                 cout<<4*(B+a/B+b/B)<<endl;
33                 return 0;
34             }
35         }
36     }
37     return 0; 
38 }

 



B.
链接: https://www.nowcoder.com/acm/contest/109/B
来源:牛客网

题目描述

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

输入描述:

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

输出描述:

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

输入

abab
ab

输出

Yes
示例2

输入

abacaba
aba

输出

No
示例3

输入

abc
ba

输出

No

kmp跑一波遇见怎么也无法匹配的点就输出no即可。
    
 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include<set>
 7 #include
 8 #include
 9 #include
10 #include 
11 #include
12 using namespace std;
13 #define mp make_pair
14 #define pb push_back
15 #define debug puts("debug")
16 #define LL long long 
17 #define pii pair
18 #define eps 1e-10
19 LL R=6371009;
20 int f[202020];
21 int g[202020];
22 char s[202020];
23 char x[202020];
24 int main()
25 {
26     int n,m,i,j,k;
27     double x1,y1,x2,y2;
28     scanf("%s%s",s,x);
29     int n1=strlen(s);
30     int n2=strlen(x);
31     f[0]=-1;
32     for(i=1;i<=n2;++i){
33         j=f[i-1];
34         while(j!=-1&&x[i-1]!=x[j]) j=f[j];
35         f[i]=j+1;
36     }
37     for(i=0,j=0;ii){
38         if(s[i]==x[j]){
39             j++;
40         }
41         else{
42             while(j!=-1&&x[j]!=s[i]) j=f[j];
43             j++;
44         }
45         if(j==n2){
46             g[i]=n2;
47             j=f[j];
48         //    j++;
49         }
50     }
51     int l=n1;
52     bool ok=1;
53 //    for(i=0;i54 //    cout<<"gi="<
55     for(i=n1-1;i>=0;--i){
56         if(g[i]==0&&l>=i){
57             ok=0;
58             break;
59         }
60         if(g[i]){
61             l=i-n2;
62         }
63     }
64     ok?puts("Yes"):puts("No");
65     return 0; 
66 }
67 
68 /*
69 ababbab
70 ab
71 */

 



C.
链接: https://www.nowcoder.com/acm/contest/109/C
来源:牛客网

题目描述

给定长度为n的数组a,定义一次操作为:
1. 算出长度为n的数组s,使得s i= (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

    首先注意到这个操作可以用矩阵来表示,设原数组为一个行向量A,k次操作之后得到的行向量B, 转移矩阵为X,则有A*Xk=B ,观察发现X是一个N*N的上三角矩阵,

牛客练习赛17_第1张图片
  可即使使用了快速幂,这个矩阵一次乘法的时间复杂度也不允许接受,因为N<=2000,N^3过于庞大,枚举了这个矩阵的前几次方之后发现一个规律,这个矩阵只要知道
第一行的元素就可以推出这个全部的矩阵,每一列都来自于第一行的一个子段,再观察发现这些数字都是杨辉三角里的数,准确的说这一行数对应杨辉三角的一列(斜着),
对于X^k,这个矩阵,第一行的元素就是( C(k-1,0) , C(k,1) , C(k+1,2),.....C(k+n-2,n-1)),组合数的公式C(n,r)=C(n,r-1)*(n-r+1)/r,
C(n,r)=C(n-1,r)+C(n-1,r-1),联立得出C(n,r)=C(n-1,r-1)*n/r,有除法记得取逆元。
  
 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include<set>
 7 #include
 8 #include
 9 #include
10 #include 
11 #include
12 using namespace std;
13 #define mp make_pair
14 #define pb push_back
15 #define debug puts("debug")
16 #define LL long long 
17 #define pii pair
18 #define eps 1e-10
19 double R=6371009;
20 
21 LL MOD=1e9+7;
22 LL q[2020];
23 LL a[2020];
24  void gcd(LL a,LL b,LL &d,LL &x,LL &y)
25   {
26       if(!b) {d=a;x=1;y=0;}
27       else {gcd(b,a%b,d,y,x);y-=x*(a/b);}
28   }
29  LL inv(LL a,LL n)
30  {
31    LL d,x,y;
32    gcd(a,n,d,x,y);
33    return d==1?(x+n)%n:-1;
34  }
35 int main()
36 {
37     LL n,m,i,j,k;
38     scanf("%lld%lld",&n,&k);
39     for(i=1;i<=n;++i) scanf("%lld",a+i);
40     k--;
41     q[1]=1;
42     for(i=2;i<=n;++i){
43         q[i]=q[i-1]*((k+i-1)%MOD)%MOD*inv(i-1,MOD);
44         q[i]%=MOD;
45     }
46     //for(i=2;i<=n;++i) q[i]+=q[i-1],q[i]%=MOD;
47     for(i=1;i<=n;++i){
48         LL tmp=0;
49         for(j=1;j<=i;++j){
50             tmp+=a[j]*q[i-j+1];
51             tmp%=MOD;
52         }
53         printf("%lld%c",tmp,i==n?'\n':' ');
54     }
55     return 0; 
56 }

 

 E.
链接:https://www.nowcoder.com/acm/contest/109/E
来源:牛客网

题目描述


给定一幅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

    全卡在C没来得及看这个其实不难,跑S+1(0和必经的S个点)次最短路,将点离散化然后dp,f[S][i]表示当前走的点的集合S且最后一个经过的点为i点的最短路径,
最后枚举全集加上dis(0,i)即可。优先队列忘记重载比较算子神特么过了样例结果一直WA,还有前向星蜜汁写错,可能老了= =
    
  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include<set>
  7 #include
  8 #include
  9 #include
 10 #include 
 11 #include
 12 using namespace std;
 13 #define mp make_pair
 14 #define pb push_back
 15 #define debug puts("debug")
 16 #define LL long long 
 17 #define pii pair
 18 #define eps 1e-10
 19 #define inf 0x3f3f3f3f
 20 struct Edge{
 21     int v,w,next;
 22 }e[202020];
 23 int first[101010],tot;
 24 void add(int u,int v,int w){
 25     e[tot].v=v;
 26     e[tot].w=w;
 27     e[tot].next=first[u];
 28     first[u]=tot++;
 29 }
 30 int f[(1<<12)][12];
 31 int d[12][101010];
 32 bool vis[101010];
 33 int x[15];
 34 int N,M,S;
 35 void dij(int s,int ps){
 36     memset(vis,0,sizeof(vis));
 37     d[ps][s]=0;
 38     priority_queue,greater >q;
 39     q.push(mp(0,s));
 40     while(!q.empty()){
 41         int u=q.top().second;
 42         q.pop(); 
 43         if(vis[u]) continue;
 44         vis[u]=1;
 45         for(int i=first[u];i!=-1;i=e[i].next){
 46             int v=e[i].v,w=e[i].w;
 47             if(d[ps][v]>d[ps][u]+w){
 48                 d[ps][v]=d[ps][u]+w;
 49                 q.push(mp(d[ps][v],v));
 50             }
 51         }
 52     }
 53 }
 54 
 55 int main()
 56 {
 57     int t,i,j,k;
 58     scanf("%d",&t);
 59     while(t--){
 60         memset(d,inf,sizeof(d));
 61         memset(first,-1,sizeof(first));
 62         tot=0;
 63         int u,v,w;
 64         scanf("%d%d",&N,&M);
 65         while(M--){
 66             scanf("%d%d%d",&u,&v,&w);
 67             add(u,v,w);
 68             add(v,u,w);
 69         }
 70         
 71 
 72         scanf("%d",&S);
 73         dij(0,0);
 74         x[0]=0;
 75         for(i=1;i<=S;++i){
 76             scanf("%d",&u);
 77             x[i]=u;
 78             dij(u,i);
 79         }
 80         memset(f,inf,sizeof(f));
 81         f[1][0]=0;
 82         for(int s=0;s<=(1<<(S+1));s++){
 83             for(j=0;j<=S;++j){
 84                 if(f[s][j]!=inf){
 85                     for(int k=0;k<=S;++k){
 86                         if((s&(1<0&&d[j][x[k]]!=inf){
 87                             f[s|(1<1<d[j][x[k]]);
 88                         }
 89                     }
 90                 }
 91             }
 92         }
 93         
 94         int ans=inf;
 95         int all=(1<<(S+1))-1;
 96         for(i=0;i<=S;++i)
 97             ans=min(ans,f[all][i]+d[0][x[i]]);
 98         cout<endl;
 99     }
100     return 0; 
101 }

 


 

转载于:https://www.cnblogs.com/zzqc/p/8995135.html

你可能感兴趣的:(牛客练习赛17)