A
题解:暴力枚举判断下第三个数是否能分解为k*k即可。
B
题解:素数筛筛2-2019中素数,再用01背包。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 3000;
int primes[N], cnt;
bool st[N];
LL dp[500][2050];
int main()
{
for(int i = 2; i <= 2019; i++) {
if(!st[i]) primes[cnt++] = i;
for(int j = 0; j < cnt && i * primes[j] <= 2019; j++) {
st[i * primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
for(int i = cnt; i >= 1; i--) primes[i] = primes[i-1];
dp[0][0] = 1;
for(int i = 1; i <= cnt; i++) // 前i个素数中总和为j的方案数
{
for(int j = 0; j <= 2019; j++)
{
dp[i][j] = dp[i-1][j];
if(j >= primes[i]) dp[i][j] += dp[i-1][j - primes[i]];
}
}
cout << dp[cnt][2019] << endl;
return 0;
}
C
题解:通过观察,要使分开后的两部分能拼接,分开的两部分必须以左下右上连成斜线对称。这样,只需对一边进行dfs即可。
#include <iostream>
#include <string>
using namespace std;
const int N = 7;
int ans;
bool st[10][10];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
void dfs(int x, int y, string s)
{
if(x + y == N) {
ans++;
//cout << s << endl;
return;
}
for(int i = 0; i < 4; i++)
{
int nx = x + dx[i], ny = y + dy[i];
if(nx > N || nx < 0 || ny > N || ny < 0 || st[nx][ny]) continue;
if((nx == 0 && x != 0) && (x != 1 || y != 0)) continue;
if(ny == 0 && y != 0) continue;
st[nx][ny] = true;
string temp =s + (char)(nx + '0') + ',' + (char)(ny + '0') + ' ';
dfs(nx, ny, temp);
st[nx][ny] = false;
}
}
int main()
{
st[N][0] = true;
st[N-1][0] = true;
string str = "";
dfs(N - 1, 0, str);
cout << ans + 1;
return 0;
}
D
题解:从小到大遍历每个数,对其分解质因数,记录每个因数出现的次数为a1, a2, a3…, 则该数的约数个数为(a1 + 1) * (a2 + 1) * (a3 + 1) …(加一是因为该因数可以不选)
#include <iostream>
#include <set>
using namespace std;
typedef long long LL;
int cal(int x)
{
int num = 0;
int ans[110] = {0};
for(int i = 2; i <= x/i; i++)
{
if(x % i == 0)
{
while(x % i == 0)
{
x /= i;
ans[num]++;
}
num++;
}
}
if(x != 1) ans[num++] = 1;
int res = 1;
for(int i = 0; i < num; i++) res *= ans[i] + 1;
return res;
}
int main()
{
for(int i = 100; ; i++)
{
if(cal(i) == 100)
{
cout << i;
break;
}
}
return 0;
}
E
题解: 从与起点相接的2个点分别开始dfs,则搜索的结束点即为另一个点,同时将路径长度减去2,因为路径开始和结束都未到起点,所以少了2
#include <iostream>
#include <string>
#include <set>
using namespace std;
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};
int st[10][10];
int ans;
void dfs(int x, int y, int len, int endx, int endy, string path)
{
if(len > 10) return;
if(x == endx && y == endy)
{
ans++;
// cout << path << " " << len << endl;
return;
}
for(int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && nx <= 5 && ny >= 0 && ny <= 5 && !st[nx][ny])
{
st[nx][ny] = true;
string np = path + char(nx + '0') + ',' + char(ny + '0') + ' ';
dfs(nx, ny, len+1, endx, endy, np);
st[nx][ny] = false;
}
}
}
int main()
{
string str = "";
st[0][0] = true;
st[1][0] = true;
dfs(1, 0, 0, 0, 1, str);
st[1][0] = false;
st[0][1] = true;
dfs(0, 1, 0, 1, 0, str);
st[0][1] = false;
cout << ans<< endl;
return 0;
}