题目链接:13届广工校赛
貌似牛客网的算法群里已经有题解的pdf了,那我不复述那么多了。 贴贴AC代码就走~~
A-跳台阶
#include <cstdio>
using namespace std;
int n;
long long a[40];
int main(){
a[1] = 1;
for (int i=2; i<=30; i++) {
a[i] = 1;
for (int j=1; j<i; j++) a[i] += a[j];
}
int T;
scanf("%d",&T);
while (T--) {
scanf("%d",&n);
printf("%lld\n",a[n]);
}
return 0;
}
B-跳一跳,很简单的
额,这题代码不是我自己写出来的,编程技巧上我还不够火候。仿照某位大神写出来的,多谢大神的代码share
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn = 1e5+1;
const int maxc = 26;
const int mod = 1e9+7;
const int seed = 29;
const int maxd = 17;
int n,Q;
int a[maxn],b[maxn],pw[maxn];
int dep[maxn],fa[maxd][maxn];
int h[maxc+1][maxn];
vector<int> e[maxn];
void init(){
pw[0] = 1;
for (int i=1; i<maxn; i++) pw[i] = (LL)pw[i-1]*seed%mod;
}
void DFS(int u){
int v;
for (int i=0; i<e[u].size(); i++) {
v = e[u][i];
dep[v] = dep[u]+1;
int ch = a[v];
for (int i=0; i<maxc; i++, (ch+=b[v])>=maxc && (ch-=maxc) )
h[i][v] = ((LL)h[i][u]*seed + ch)%mod;
DFS(v);
}
}
inline int Min(int x, int y) {return x<y?x:y; }
int main(){
int T;
scanf("%d",&T);
init();
while (T--){
scanf("%d",&n);
for (int i=0; i<=n; i++) e[i].clear();
memset(h,0,sizeof(h));
char op[2];
for (int i=2; i<=n; i++) {
scanf("%d%s%d",&fa[0][i],op,&b[i]);
e[fa[0][i]].push_back(i);
a[i] = op[0] - 'a';
b[i] %= maxc;
}
for (int i=1; 1<<i <= n; i++) {
for (int j=1; j<=n; j++) fa[i][j] = fa[i-1][fa[i-1][j]];
}
dep[1] = 0;
DFS(1);
int u,v,w;
int uh,vh;
int uc,vc;
scanf("%d",&Q);
while (Q--) {
scanf("%d%d%d",&u,&v,&w);
w %= maxc;
for (int i=maxd-1; i>=0; i--) {
if (Min(dep[u],dep[v]) < 1<<i) continue;
uh = (h[w][u] - (LL)h[w][fa[i][u]]*pw[1<<i])%mod;
vh = (h[w][v] - (LL)h[w][fa[i][v]]*pw[1<<i])%mod;
if (uh<0) uh += mod;
if (vh<0) vh += mod;
if (uh == vh) {
u = fa[i][u];
v = fa[i][v];
}
}
uc = (a[u] + w*b[u]) % maxc;
vc = (a[v] + w*b[v]) % maxc;
if (uc<vc) printf("<\n");
else if (uc == vc) printf("=\n");
else printf(">\n");
}
}
return 0;
}
C-平分游戏
正解讲的不太好,推荐一个很好的blog:点击打开链接
注: n == k 的情况应该直接输出gg吧,但加上这句我就gg了。。 去掉之后AC了。。
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e6+5;
bool vis[maxn];
LL a[maxn];
LL sum,avg,ans;
int n,k;
vector<LL>g;
bool flag;
LL cal(){
int sz = g.size();
g[sz-1] = 0;
sort(g.begin(),g.end());
return g[sz/2];
}
int main(){
while (scanf("%d%d",&n,&k)==2) {
// if (n == k) { printf("gg\n"); continue; }
k = min(n-1,k);
flag = 1;
sum = 0; ans = 0;
for (int i=0; i<n; i++) {
scanf("%lld",&a[i]);
sum += a[i];
}
avg = sum / n;
if (sum%n) {
printf("gg\n");
continue;
}
memset(vis,0,sizeof(vis));
for (int i=0; i<n; i++) if (!vis[i]) {
LL t = 0, p = 0;
int pt = i;
g.clear();
while (!vis[pt]) {
g.push_back(a[pt]-avg+p);
p = g[g.size()-1];
vis[pt] = 1;
t += a[pt];
pt = (pt+k+1)%n;
}
int sz = g.size();
if (t/sz!=avg || t%sz) {
flag = 0;
break;
}
LL mid = cal();
for (int k=0; k<sz; k++) ans += abs(mid-g[k]);
}
if (!flag) printf("gg\n"); else printf("%lld\n",ans);
}
return 0;
}
D-psd面试
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1500;
int dp[maxn][maxn];
char s[maxn];
int n;
int main(){
while (scanf("%s",s)==1) {
n = strlen(s);
memset(dp,0,sizeof(dp));
for (int i=0; i<n; i++) if (s[i]>='A' && s[i]<='Z') s[i] = s[i]-'A'+'a';
for (int i=0; i<n; i++) dp[i][i] = 1;
for (int i=1; i<n; i++) {
int t = 0;
for (int j=0; j+i<n; j++) {
if (s[j] == s[j+i]) t = dp[j+1][j+i-1]+2;
else t = max(dp[j+1][j+i],dp[j][j+i-1]);
dp[j][j+i] = t;
}
}
printf("%d\n",n-dp[0][n-1]);
}
return 0;
}
E-回旋星空
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1000+10;
struct Point{
int x,y;
}p[maxn];
int n,ans;
int x,y;
int d[maxn];
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%d",&n);
for (int i=1; i<=n; i++) scanf("%d%d",&p[i].x,&p[i].y);
ans = 0;
for (int i=1; i<=n; i++) {
x = p[i].x;
y = p[i].y;
for (int j=1; j<=n; j++) d[j] = (x-p[j].x)*(x-p[j].x) + (y-p[j].y)*(y-p[j].y);
sort(d+1,d+n+1);
int pt = 1;
for (int j=2; j<=n; j++) if (d[pt]==d[j]) ans++; else pt = j;
}
if (ans==0) printf("WA\n"); else printf("%d\n",ans*2);
}
return 0;
}
F-等式
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 70;
int a[maxn],tot;
int ans,n;
int main(){
int T;
scanf("%d",&T);
while (T--) {
scanf("%d",&n);
tot = 0;
memset(a,0,sizeof(a));
for (int i=2; i*i<=n; i++) if (n%i==0) {
while (n%i==0) a[tot]++, n/=i;
tot++;
}
if (n>1) a[tot++]++;
for (int i=0; i<tot; i++) a[i]<<=1;
ans = 1;
for (int i=0; i<tot; i++) ans *= (a[i]+1);
printf("%d\n",(ans+1)/2);
}
return 0;
}
G-旋转矩阵
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
const int maxL = 10000;
const int maxn = 40;
char s[maxn][maxn];
int n,m;
char str[maxL];
stack<int>st;
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) scanf("%s",s[i]+1);
while (!st.empty()) st.pop();
scanf("%s",str);
int len = strlen(str);
for (int i=0; i<len; i++) {
if (st.empty()) {
if (str[i]=='L') st.push(0); else st.push(1);
continue;
}
if (st.top()==0 && str[i]=='R') { st.pop(); continue; }
if (st.top()==1 && str[i]=='L') { st.pop(); continue; }
if (str[i]=='L') st.push(0); else st.push(1);
}
int sz = st.size();
sz %= 4;
if (sz == 0) {
printf("%d %d\n",n,m);
for (int i=1; i<=n; i++) printf("%s\n",s[i]+1);
printf("\n");
continue;
}
if (sz == 1 || sz == 3) {
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++) {
if (s[i][j]=='-') s[i][j] = '|';
else if (s[i][j]=='|') s[i][j] = '-';
}
}
if (sz == 2) {
printf("%d %d\n",n,m);
for (int i=n; i>=1; i--) {
for (int j=m; j>=1; j--) printf("%c",s[i][j]);
printf("\n");
}
printf("\n");
continue;
}
printf("%d %d\n",m,n);
if (st.top()==0 && sz==1 || st.top()==1 && sz==3) {
for (int j=m; j>=1; j--) {
for (int i=1; i<=n; i++) printf("%c",s[i][j]);
printf("\n");
}
printf("\n");
continue;
}
for (int j=1; j<=m; j++) {
for (int i=n; i>=1; i--) printf("%c",s[i][j]);
printf("\n");
}
printf("\n");
}
return 0;
}
H-哲哲的疑惑
正解的数学变换非常复杂,我是看不懂了。。
推荐一个博客,讲述的不错,虽然思维跳跃大,但能直观的知道最后结果是怎么来的。
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
LL n,m,l;
const LL p = 998244353;
LL quick_pow(LL a, LL b) {
LL res = 1;
while (b) {
if (b&1) res = (res*a)%p;
b>>=1;
a = (a*a)%p;
}
return res;
}
LL C(LL n , LL m) {
if (n<m) return 0;
LL ans = 1;
for (LL i=1; i<=m; i++) ans = ans*i%p;
ans = quick_pow(ans,p-2);
for (LL i=n; i>n-m; i--) ans = ans*i%p;
return ans;
}
int main(){
while (scanf("%lld%lld%lld",&n,&m,&l)==3) {
printf("%lld\n",quick_pow(n-m,l)*C(n,m)%p);
}
return 0;
}
I-填空题
#include <cstdio>
using namespace std;
int main(){
printf("ac\n");
return 0;
}
J-强迫症的序列
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100000+5;
int a[maxn];
int n;
int total,t;
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%d",&n);
for (int i=1; i<=n; i++) scanf("%d",&a[i]);
total = 0;
sort(a+1,a+n+1);
int sum = 0;
t = a[n]-a[1];
total += a[n]-a[1];
for (int i=1; i<n; i++) a[i]+=t, sum += a[i] - a[n];
total += sum;
printf("%d %d\n",total,a[1]+sum);
}
return 0;
}
K-密码
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 100000+10;
int n,len,start;
char s[maxn];
vector<char> G[maxn];
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%d",&n);
scanf("%s",s);
len = strlen(s);
for (int i=1; i<=n; i++) G[i].clear();
if (n==1) { printf("%s\n",s); continue; }
bool dir = 1;
int cnt = 1;
for (int i=0; i<len; i++) {
if (cnt<=n && dir==1) {
G[cnt].push_back(s[i]);
cnt++;
if (cnt>n) {cnt = n-1; dir=0;}
}
else if (cnt>=1 && dir==0) {
G[cnt].push_back(s[i]);
cnt--;
if (cnt<1) {cnt = 2; dir = 1;}
}
}
for (int i=1; i<=n; i++) {
for (int j=0; j<G[i].size(); j++) printf("%c",G[i][j]);
}
printf("\n");
}
return 0;
}
L-用来作弊的药水
#include <cstdio>
#include <cmath>
using namespace std;
const double eps = 1e-3;
int x,y,a,b;
double p,q;
int main(){
int T;
scanf("%d",&T);
while (T--) {
scanf("%d%d%d%d",&x,&a,&y,&b);
p = (double)a*log2(x);
q = (double)b*log2(y);
if (fabs(p-q)<eps) printf("Yes\n"); else printf("No\n");
}
return 0;
}
最后附上一张补完题目的图,这次比赛学到了不少东西吧,补完题也挺有成就感的。