这次比赛的确比较水23333
A长方体
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
输入描述:
一行三个整数a, b, c表示面积(1 <= a, b, c <= 10000)。
输出描述:
一行一个整数表示边长和。
输入
1 1 1
输出
12
输入
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 ",ans); 24 return 0; 25 }
B 好位置
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
定义s中的某一位i为好的位置,当且仅当存在s的子序列 满足y=x且存在j使得i=kj成立。
问s中是否所有的位置都是好的位置。
输入描述:
一行两个字符串s,x,这两个串均由小写字母构成。
1 <= |s|, |x| <= 200000
输出描述:
Yes表示是。
No表示不是。
输入
abab ab
输出
Yes
输入
abacaba aba
输出
No
输入
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 "); 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 "); 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 "); 80 return 0; 81 } 82 for(int i=0;i<lenss;i++) 83 if(!vis[ss[i]-'a']) 84 { 85 printf("No "); 86 return 0; 87 } 88 printf("Yes "); 89 return 0; 90 }
C 操作数
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
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);i
第二行n个整数表示a数组(0 <= a
<= 1,000,000,000)。
输出描述:
一行n个整数表示答案。
输入
3 1 1 2 3
输出
1 3 6
输入
5 0 3 14 15 92 6
输出
3 14 15 92 6
加和类的问题肯定是和组合数有关系的啦。
首先是
$ egin{bmatrix} a_1 & a_2 & a_3 & ……& a_n end{bmatrix}quad $ $ egin{bmatrix}1 & 1 & 1 & …… & 1 \ 0 & 1 & 1 & …… & 1 \ 0 & 0 & 1 & …… & 1 \ …… & …… & …… & …… & …… \ 0 & 0 & 0 & …… & 1 end{bmatrix}^{k-1} quad $
然后你求后面这个矩阵k-1次方以后会发现其实他是:
$ egin{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 ",ans[n]); 63 return 0; 64 }
D 经纬度
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
输入描述:
第一行一个整数T表示数据组数。
接下来n行,每行四个数lat1, lng1, lat2, lng2分别表示两个点的经纬度。
正数表示北纬和东经。
负数表示南纬和西经。
数据保证合法。
输出描述:
n行表示答案。
答案保留到米。
输入
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 ",ballen-linlen); 35 } 36 return 0; 37 }
E 求长度
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
输入描述:
第一行一个整数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 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 ",ans); 106 } 107 return 0; 108 }
F 玩游戏
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
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'。
输入
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 "); 29 else printf("Bob "); 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 "); 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 "); 50 continue; 51 } 52 } 53 printf("Bob "); 54 continue; 55 } 56 return 0; 57 }