A:
1、2019<X<Y
2、2019^2, X^2, Y^2构成等差数列
满足条件的X和Y可能有多种情况,请给出X+Y的值,并且令X+Y尽可能的小。
思路:暴力求解
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
int main()
{
int i,j;
for(i=2020;i<100000;i++)
{
for(j=i+1;j<100000;j++)
{
if(j*j-i*i==i*i-2019*2019)
{
cout<<i+j<<endl;
return 0;
}
}
}
return 0;
}
答案:7020
B:
2019可以被分解成若干个两两不同的素数,请问不同的分解方案有多少种?
注意:分解方案不考虑顺序,如2+2017=2019和2017+2=2019属于同一种方案。
思路:典型的01背包问题。
线性素数筛求出2019以内的所有素数,每个素数只能取或不取,不能多次出现,dp[j]表示前i个素数能组成数字j的方案数。
状态转移方程dp[j]+=dp[j-prime[i]];表示能构成数字j的方案数是以下两者之和:
(1)不取第i个素数,前i-1个素数能构成j的方案数。
(2)取第i个素数,能构成j的方案数,也就是构成数字(j-prime[i])的方案数。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
using namespace std;
int prime[1010],isprime[2050],num;
long long dp[2050];
void init()
{
int i,j;
for(i=2;i<=2019;i++)
{
if(isprime[i]==1)
prime[num++]=i;
for(j=0;j<num&&i*prime[j]<=2019;j++)
{
isprime[i*prime[j]]=0;
if(i%prime[j]==0)
break;
}
}
}
int main()
{
int i,j;
for(i=0;i<=2019;i++)
isprime[i]=1;
dp[0]=1;
init();
for(i=0;i<num;i++)
for(j=2019;j>=prime[i];j--)
dp[j]+=dp[j-prime[i]];
cout<<dp[2019]<<endl;
return 0;
}
答案:55965365465060
C:
思路:搜索。切成两半,每部分都关于副对角线对称。切的时候只考虑左边的一半就可以,剩下的另一半一定也成立。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
int book[10][10];
int nextx[4]={1,-1,0,0};
int nexty[4]={0,0,-1,1};
int ans=0;
void dfs(int x,int y)
{
if(x==0||y==7)
{
ans++;
return;
}
for(int i=0;i<4;i++)
{
int nx=x+nextx[i];
int ny=y+nexty[i];
if(nx>=0&&ny>=0&&nx<=7&&ny<=7&&book[nx][ny]==0&&nx!=ny)
{
book[nx][ny]=1;
dfs(nx,ny);
book[nx][ny]=0;
}
}
}
int main()
{
for(int i=0;i<=7;i++)
{
book[i][i]=1;
dfs(i,i);
book[i][i]=0;
}
cout<<ans<<endl;
return 0;
}
答案:2444
D:
有1个约数的最小数为1(1),有两个约数的最小数为2(1,2)……
有n个约数的最小数为Sn
S1=1 (1)
S2=2 (1 2)
S3=4 (1 2 4)
S4=6 (1 2 3 6)
求S100
思路:暴力
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
using namespace std;
int main()
{
int i,j,cnt;
for(i=100;;i++)
{
cnt=0;
for(j=1;j<=i;j++)
{
if(i%j==0)
cnt++;
}
if(cnt==100)
break;
}
cout<<i;
return 0;
}
答案:45360
E:
有一个5X5的方格。方格左上角顶点坐标为(0,0),右下角坐标为(5,5)。
求满足下列条件的路径条数:
1、起点和终点都是(0,0)
2、路径不自交
3、路径长度不大于12
4、对于每一个顶点,有上下左右四个方向可以走,但是不能越界。
思路:深搜
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
long long ans;
int nextx[4]={1,-1,0,0};
int nexty[4]={0,0,1,-1};
int book[10][10],vis;
void dfs(int x,int y,int cnt)
{
if(x==0&&y==0&&cnt<=12&&vis==1)
{
ans++;
return;
}
if(cnt>=12)
return;
vis=1;
int i,nx,ny;
for(i=0;i<4;i++)
{
nx=x+nextx[i];
ny=y+nexty[i];
if(nx>=0&&nx<=5&&ny>=0&&ny<=5&&book[nx][ny]==0)
{
book[nx][ny]=1;
dfs(nx,ny,cnt+1);
book[nx][ny]=0;
}
}
}
int main()
{
vis=0;
dfs(0,0,0);
cout<<ans-2<<endl;
return 0;
}
答案:206(需要剪掉两个路线(0,0)->(1,0)->(0,0)和(0,0)->(0,1)->(0,0),这两个路线都发生了路径自交)
F:
题目给定两个字符串S和T,保证S的长度不小于T的长度,问至少修改S的多少个字符,可以令T成为S的子序列。
样例输入1:
ABCDABCD
AABCX
样例输出1:
1
样例输入2:
ABCDABCD
XAAD
样例输出2:
2
样例输入3:
XBBBBBAC
ACC
样例输出3:
2
思路:dp
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
int dp[1010][1010];
int main()
{
char s[1010],t[1010];
scanf("%s",s+1);
getchar();
scanf("%s",t+1);
int n=strlen(s+1),m=strlen(t+1),i,j;
memset(dp,inf,sizeof(dp));
for(i=0;i<=n;i++)
dp[i][0]=0;
for(j=1;j<=m;j++)
{
for(i=j;i<=n;i++)
{
if(s[i]==t[j])
dp[i][j]=dp[i-1][j-1];
else
dp[i][j]=min(dp[i-1][j-1]+1,dp[i-1][j]);
}
}
cout<<dp[n][m]<<endl;
return 0;
}