A 跳台阶
https://ac.nowcoder.com/acm/contest/90/A
规律为方法总数=
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
long long sum=0;
sum=pow(2,n-1);
printf("%lld\n",sum);
}
return 0;
}
B 跳一跳,很简单的
https://ac.nowcoder.com/acm/contest/90/B
知识盲区,待补
C 平分游戏
https://ac.nowcoder.com/acm/contest/90/C
比赛没写出来,赛后思路来源:https://www.cnblogs.com/jiachinzhao/p/8650297.html
代码实现中标注了细节
#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
const int N = 1e6 + 10;
int a[N],vis[N];
LL b[N];
int n, k;
LL cal(int cnt){
b[cnt - 1] = 0;
sort(b, b + cnt);
return b[cnt / 2];
}
int main()
{
cin>>n>>k;
k = min(k, n - 1);
LL sum = 0;
for(int i = 0;i < n;i++){
scanf("%d",a + i);
sum += a[i];
}
if(sum % n ){
puts("gg");
return 0;
}
LL ans = 0, avg = sum / n;
for(int i = 0;i < n;i++){
if(!vis[i]){
int j = i,cnt = 0;
LL tmp = 0,p = 0;
while(!vis[j]){
vis[j] = 1;
//b数组的值为a0+a1+...+an-(n+1)*avg
//p的值表示为a0+a1+...+an-1-n*avg
b[cnt] = a[j] - avg + p, tmp += a[j];
p = b[cnt++];
//环上的数字求和
j = (j + k + 1) % n;
}
//tmp表示环上的数字总和,cnt为环上的数字个数
if(tmp % cnt || tmp / cnt != avg){
puts("gg");
return 0;
}
LL midnum = cal(cnt);
for(int k = 0;k < cnt;k++)
ans += abs(midnum - b[k]);
}
}
printf("%lld\n",ans);
return 0;
}
D psd面试
https://ac.nowcoder.com/acm/contest/90/D
最长回文子序列,直接套板子。首先将字符串的大小写统一,最后的结果为数组的长度减去最长子序列的长度
#include<iostream>
#include<vector>
#include<cstring>
#include<string>
using namespace std;
int longestPalindromeSubSequence1(string str)
{
int n=str.length();
vector<vector<int> > dp(n,vector<int>(n));
for(int j=0;j<n;j++){
dp[j][j]=1;
for(int i=j-1;i>=0;i--){
if(str[i]==str[j])
dp[i][j]=dp[i+1][j-1]+2;
else
dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][n-1];
}
int longestPalindromeSubSequence2(string str){
int n=str.length();
vector<vector<int> > dp(n,vector<int>(n));
for(int i=n-1;i>=0;i--){
dp[i][i]=1;
for(int j=i+1;j<n;j++){
if(str[i]==str[j])
dp[i][j]=dp[i+1][j-1]+2;
else
dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][n-1];
}
int main()
{
string s;
int length;
while(cin>>s)
{
for(int i=0;i<s.size();i++)
{
if(s[i]>='a'&&s[i]<='z')
s[i]=s[i]-32;
}
length=longestPalindromeSubSequence2(s);
cout<<s.size()-length<<endl;
}
return 0;
}
E 回旋星空
https://ac.nowcoder.com/acm/contest/90/E
一直在想先枚举i,再根据j枚举k,发现超时后想到在确定j枚举k的过程中使用二分,再然后就想不出了......
这里的正解思路为枚举中间节点j的数值,然后查找是否有两个长度相等的线段距离,最后结果数*2即为正确答案。在计算距离时没有开放,直接使用long long进行保存
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1011;
vector<long long> p[MAXN];
struct node{
int x,y;
};
vector<node> q;
bool cmp(node a,node b) {
if(a.x==b.x)
return a.y<b.y;
else
return a.x<b.x;
}
long long distou(node a,node b) {
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
int n;
scanf("%d",&n);
q.clear();
for(int i=0;i<n;i++) {
node temp;
scanf("%d%d",&temp.x,&temp.y);
q.push_back(temp);
}
if(n<=2) {
puts("WA");
continue;
}
sort(q.begin(),q.end(),cmp);
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
long long sum1=distou(q[i],q[j]);
p[i].push_back(sum1);
}
}
int cnt=0;
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(j!=i) {
long long ans=p[i][j];
for(int k=0;k<n;k++) {
if(k!=i&&ans==p[j][k])
cnt++;
}
}
}
}
if(cnt!=0)
printf("%d\n",cnt);
else
puts("WA");
}
return 0;
}
F 等式
https://ac.nowcoder.com/acm/contest/90/F
首先等式可以化简为 然后我就卡了......其实答案就在转角,在多化简一步后为
对于求解其因子个数即可得出答案
#include<bits/stdc++.h>
using namespace std;
//(x-n)*(y-n)==n*n
int main()
{
int T,N;
scanf("%d",&T);
while(T--) {
scanf("%d",&N);
//求N*N的因数
int ans=1;
for(int i=2;i*i<N;i++) {
int temp=0;
while(N%i==0) {
temp++;
N/=i;
}
ans*=(temp*2+1);
}
if(N>1)
ans*=3;//剩下一个大素数,则N^2有两个大素数,所以ans*(2+1)
printf("%d\n",(ans-1)/2+1);
}
return 0;
}
G 旋转矩阵
https://ac.nowcoder.com/acm/contest/90/G
模拟题,使用cnt变量记录左转和右转的次数
#include<bits/stdc++.h>
using namespace std;
const int MAXN=50;
char s[MAXN][MAXN];
int main() {
int t;
scanf("%d",&t);
while(t--) {
int n,m;
scanf("%d%d",&n,&m);
getchar();
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++)
scanf("%c",&s[i][j]);
getchar();
}
int cnt=0;
string z;
cin>>z;
for(int i=0;i<z.length();i++) {
if(z[i]=='L')
cnt--;
else
cnt++;
}
if(cnt>=0)
cnt%=4;
else {
while(cnt<0)
cnt+=4;
cnt%=4;
}
if(cnt==0) {
printf("%d %d\n",n,m);
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++)
printf("%c",s[i][j]);
printf("\n");
}
}
if(cnt==1){
printf("%d %d\n",m,n);
for(int i=0;i<m;i++) {
for(int j=n-1;j>=0;j--) {
if(s[j][i]=='-')
printf("|");
else {
if(s[j][i]=='|')
printf("-");
else
printf("%c",s[j][i]);
}
}
printf("\n");
}
}
if(cnt==2) {
printf("%d %d\n",n,m);
for(int i=n-1;i>=0;i--) {
for(int j=m-1;j>=0;j--)
printf("%c",s[i][j]);
printf("\n");
}
}
if(cnt==3) {
printf("%d %d\n",m,n);
for(int i=m-1;i>=0;i--) {
for(int j=0;j<n;j++) {
if(s[j][i]=='-')
printf("|");
else {
if(s[j][i]=='|')
printf("-");
else
printf("%c",s[j][i]);
}
}
printf("\n");
}
}
printf("\n");
}
return 0;
}
H 哲哲的疑惑
https://ac.nowcoder.com/acm/contest/90/H
比赛的时候也没写出来......数论只会GCD 在取模的过程中如果模数是素数,使用快速幂求取逆元求解
详情可参考这篇博客 https://www.cnblogs.com/YuXiaoze/p/11637793.html
#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long n,m,l;
inline long long ksm(long long a,long long p) {
long long re=1;
while(p) {
if(p&1)
re=re*a%mod;
p>>=1;
a=a*a%mod;
}
return re;
}
inline long long C() {
long long re=1,cmp=1;
for(long long i=m+1;i<=n;i++)
re=re*i%mod;
for(long long i=2;i<=n-m;i++)
cmp=cmp*i%mod;
return re*ksm(cmp,mod-2)%mod;
}
int main() {
scanf("%lld%lld%lld",&n,&m,&l); // C(n,m)*(n-m)^l
if(n<m)
printf("0");
else
printf("%lld",ksm(n-m,l)*C()%mod);
return 0;
}
I 填空题
https://ac.nowcoder.com/acm/contest/90/I
签到题
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
printf("ac\n");
return 0;
}
J 强迫症的序列
https://ac.nowcoder.com/acm/contest/90/J
每次给n-1个元素加1,其实相当于每次给前n-1个小的数+1,直到所有的数字都为同一个和。那么可以将初始数组按照从小到大排序,然后每次只加前n-1个数进行模拟。再进一步想,对于n-1个小的数+1,相当于对最大数-1,每次都对序列中的最大数-1直至所有数相等,那么这个相等的数会是什么呢,没错就是原本的最小值。只需要在一开始将除了最小数的其他数字都减去最小数,求和,结果就是操作的步数。最终的结果就是最小值加上这个数值即为最终所有的数的结果。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int num[120000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(num,0,sizeof(num));
int n,sum=0,sum1=0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>num[i];
sum+=num[i];
}
sort(num,num+n);
for(int i=1;i<n;i++)
sum1+=num[i]-num[0];
printf("%d %d\n",sum1,num[0]+sum1);
}
return 0;
}
K 密码
https://ac.nowcoder.com/acm/contest/90/K
模拟
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
const int maxn=10000000+100;
char s1[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,t1=0;
cin>>n;
scanf("%s",s1);
//getchar();
int len1=strlen(s1)-1;
if(n==1)
printf("%s\n",s1);
else
{
int k1=2*(n-1);
int sum1=0;
while(sum1<=len1)
{
printf("%c",s1[sum1]);
sum1+=k1;
}
for(int i=1;i<(n-1);i++)
{
int k=2*(n-1-i);
int k1=2*i;
int sum=i;
while(sum<=len1)
{
printf("%c",s1[sum]);
sum+=k;
if(sum<=len1)
printf("%c",s1[sum]),sum+=k1;
else
break;
}
}
k1=2*(n-1);
sum1=n-1;
while(sum1<=len1)
{
printf("%c",s1[sum1]);
sum1+=k1;
}
printf("\n");
}
}
return 0;
}
L 用来作弊的药水
https://ac.nowcoder.com/acm/contest/90/L
可以直接暴力判定,使用对数判定是否相等即可
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
long long x,a,y,b;
cin>>x>>a>>y>>b;
if(fabs(a*log(x)-b*log(y))<1e-5)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}