计概杂烩2021

发布时间 2023-12-16 12:47:46作者: oierwyh

2021期末

A+B Problem?

#include <stdio.h>
int main(void) { 
    int a,b,d;char c;scanf("%d%c%d",&a,&c,&b);
    if(c=='+') d=a+b;
    if(c=='-') d=a-b;
    if(c=='*') d=a*b;
    if(c=='/') d=a/b;
    printf("%d\n",d);
	return 0;
}

乘坐北京地铁

#include <stdio.h>

int main(void) { 
    int n,k;scanf("%d%d",&k,&n);
    double ans;
    if(n<=6) ans=3;
    else if(n<=12) ans=4;
    else if(n<=22) ans=5;
    else if(n<=32) ans=6;
    else{
        if((n-32)%10==0) ans=(n-32)/10+6;
        else ans=(n-32)/10+7;
    }
    if(k>=150) ans*=0.5;
    else if(k>=100) ans*=0.8;
    printf("%.2lf\n",ans);
	return 0;
}

细菌共生

#include <stdio.h>

int a[4000];

int main(void) { 
    int n,ans=0,cnt=0;scanf("%d",&n);
    for(int i=1;i<=n;++i) {scanf("%d",&a[i]);if(ans<a[i]) ans=a[i];}
    for(int i=1;i<=n;++i)
        if(a[i]<=ans/2)
            ++cnt;
    printf("%d\n",n-cnt);
	return 0;
}

机试排名

#include <stdio.h>

int a[400],b[400];

int main(void) {
    int n;scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&a[i],&b[i]);
    for(int i=1;i<n;++i)
        for(int j=i+1;j<=n;++j)
            if(b[i]<b[j]||(b[i]==b[j]&&a[i]>a[j]))
                {int tmp=a[i];a[i]=a[j];a[j]=tmp;
                tmp=b[i];b[i]=b[j];b[j]=tmp;}
    for(int i=1;i<=n;++i)
        printf("%d\n",a[i]);
	return 0;
}

解密文本(encode)

#include <stdio.h>
#include <string.h>

int n,a[200];
char c[200];

int main(void) { 
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    scanf("\n%s",c);int l=strlen(c);
    for(int i=1;i<=n;++i)
        printf("%c",a[i]+c[(i+l-1)%l]);
	return 0;
}

通过模运算实现“延申”操作(当然也可以直接延伸)

堆盘子(placement)

#include <stdio.h>

int a[2000][2000];
int x1[9]={0,0,0,1,1,1,-1,-1,-1};
int y1[9]={0,1,-1,0,1,-1,0,1,-1};

void add(int x,int y)
{
    for(int i=0;i<9;++i)
        ++a[x+x1[i]][y+y1[i]];
}

int main(void) { 
    int n,m,k,ans=0,cnt=1;scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;++i)
    {
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        {
            if(ans==a[i][j]) ++cnt;
            if(ans<a[i][j]) {cnt=1;ans=a[i][j];}
        }
    printf("%d %d\n",ans,cnt);
	return 0;
}

网络迷因

#include <stdio.h>
#include <string.h>

char a[200][200],b[200][200];
char c1[200],c2[200];
char q[200][200];
int n,cnt;

int main()
{ 
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%s%s",a[i],b[i]);
	}
	scanf("%s%s",c1,c2);
	if(strcmp(c1,c2)==0)
	{
		printf("Yes\n");
		return 0;
	}
	for(int i=1;i<=n;++i)
	{
		if(strcmp(c1,a[i])==0)
			strcpy(q[++cnt],b[i])
			,strcpy(a[i],""),strcpy(b[i],"");
		if(strcmp(c1,b[i])==0)
			strcpy(q[++cnt],a[i])
			,strcpy(a[i],""),strcpy(b[i],"");
	}
	for(int x=1;x<=cnt;++x)
	{
		if(strcmp(q[x],c2)==0)
		{
			printf("Yes\n");
			return 0;
		}
		for(int i=1;i<=n;++i)
		{
			if(strcmp(q[x],a[i])==0)
				strcpy(q[++cnt],b[i]),
				strcpy(a[i],""),strcpy(b[i],"");
			if(strcmp(q[x],b[i])==0)
				strcpy(q[++cnt],a[i]),
				strcpy(a[i],""),strcpy(b[i],"");
		}
	}
	printf("No\n");
	return 0;
}

方法一:定义一个队列,先把c1放进去,然后把与c1等价的都放进去,重复这一过程直到c2入队或者全部入了一遍队为止。注意入队的时候要标记出来避免重复入队。
方法二:并查集+哈希(好复杂,没写)

电话密码

#include <stdio.h>
#include <string.h>

char a[20][20]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
char b[20],c[20];
int d[20]={0,0,3,3,3,3,3,4,3,4};
int l,cnt;

void f(int x){
    if(x==l){
		puts(c);
        return;
    }
    int m=b[x]-'0';
    for(int i=0;i<d[m];++i){
        c[cnt++]=a[m][i];
        f(x+1);
        --cnt;
    }
}

int main(void) {
	gets(b);
    l=strlen(b);
    f(0);
	return 0;
}

递归,每一次找一位数入队并记录方案即可

连续正面的可能性

#include <stdio.h>

int n,m,ans;
int f[200][200][200];

int main(void) { 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) f[i][0][0]=f[i][i][i]=1;
    for(int i=2;i<=n;++i)
    {
    	for(int j=1;j<i;++j)//unnecessery to check j==1 and j==i
    	{
    		for(int k=0;k<=j;++k)
    			f[i][j][0]+=f[i-1][j][k];
    		for(int k=1;k<j;++k)
    			f[i][j][k]+=f[i-1][j][k-1];
			f[i][j][j]+=f[i-1][j-1][j-1]+f[i-1][j][j-1];
		}
	}
	for(int k=0;k<=m;++k) ans+=f[n][m][k];
	printf("%d\n",ans);
	/*
	for(int i=0;i<=n;++i)
		for(int j=0;j<=i;++j)
			for(int k=0;k<=j;++k)
				printf("f[%d][%d][%d]=%d\n",i,j,k,f[i][j][k]);
	*/
	return 0;
}

文心一言似乎有一个\(O(n^2)\)的做法,但是有点瑕疵,我也没能帮他改过来(到底谁是AI

我只想到了这个\(O(n^3)\)的三维dp

\(f[i][j][k]\)表示i枚硬币最多连续j面朝上且最末尾有k面朝上的方法数

则:

(1) k=0 那前n-1位可以是任意数,\(f[i][j][0]=\Sigma_{k=0}^jf[i-1][j][k]\)
(2) 0<k<j 那么j枚连续朝上的面一定不出现在最后面,所以\(f[i][j][k]=f[i-1][j][k-1]\)
(3) k=j 那么有两种可能:只有最后面j位连续正面是唯一最多的,和前面已经有j位连续正面,最后面又有j位连续正面,所以\(f[i][j][j]=f[i-1][j-1][j-1]+f[i-1][j][j-1]\)

这是合理的状态转移方程!然后跑dp就完事了,最后结果就是\(\Sigma_{k=0}^mf[n][m][k]\)