有的时候要把算法题看成一道数学题来写,这样子可能会有新的思路,而不仅仅只是想想有什么算法思想。
去年真的是失策了,第二场真的比第一场好做很多很多。
填空题
第一题:求余
参考答案:1
咱就是说这道题目口算也能出结果1
当然你要是想要表达一下自己的变成能力也不是不行对吧,嘿嘿
#include<bits/stdc++.h>
using namespace std;
int main()
{
printf("%d",2021%20);
return 0;
}
第二题:双阶乘
参考答案:36079
这是一个填空题,且我们已经知道了我们所要求的那个书,可以直接放进去,不用读入了。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n=2021;
int res=1;
for(int i=1;i<=2021;i+=2)
res*=i%100000;
cout<<res%100000<<endl;
return 0;
}
第三题:格点
参考答案:15698
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long res=0;
int i=1,j=1;
for( i=1; i<=2021; i++)
for( j=1; i*j<=2021; j++)//也可以判断条件写成j<=2021
if(i*j<=2021)
res++;
cout<<res<<endl;
return 0;
}
第四题:整数分解(记忆化搜索/数学隔板法)
参考答案:691677274345
写法一:记忆化搜索
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[10][2030];
//前面的数是代表着分解成了几个数
//后面的数代表着所分解的数的大小
ll dfs(int k,int n)
{
if(f[k][n]!=-1)return f[k][n];
if(!k)
//这里说明了,如果k是0那么只有在n是0的时候才可以有一种情况,否则都是不成立的
{
if(!n)
return 1;
return 0;
}
f[k][n]=0;//初始值
for(int i=1;i<=n;i++)
f[k][n]+=dfs(k-1,n-i);//妙啊,细细品味啊
retunr f[k][n];
}
int main()
{
memset(f,-1,sizeof f);
cout<<dfs(5,2021)<<endl;
return 0;
}
写法二:数学隔板法
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long num1=1;
int num2=4*3*2*1;
for(int i=2020;i>=2017;i--)
num1*=i;
cout<<num1/num2;
return 0;
}
第五题:城邦(最小生成树:Kruskal)
+)
{
int w=get_cost(a,b);
e[k++]={a,b,w};
}
sort(e,e+k);
int ans=0;
for(int i=0;i<k;i++)
{
int a=e[i].a,b=e[i].b;
if(find(a)!=find(b))
{
ans+=e[i].w;
p[find(a)]=find(b);
}
}
cout<<ans<<endl;
return 0;
}
编程题
第六题:特殊年份
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
int res=0;
for(int i=0;i<5;i++)
{
cin>>s;
if(s[0]==s[2]&&s[1]==s[3]-1)
res++;
}
cout<<res<<endl;
return 0;
}
第七题:小平方
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int res=0;
for(int i=1;i<n;i++)
{
if(i*i%n*2<n)//这样子可以避免处理精度的问题
res++;
}
cout<<res<<endl;
return 0;
}
第八题:完全平方数(质因数分解)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n;
cin>>n;
ll res=1;
//质因数分解
for(ll i=2;i*i<=n;i++)
if(n%i==0)
{
int s=0;
while(n%i==0)
s++,n/=i;
//质因数分解,让所有的质数的指数全是偶数倍
if(s%2)res*=i;
}
if(n>1)res*=n;
cout<<res<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n;
cin>>n;
ll res=1;
//质因数分解
for(ll i=2;i*i<=n;i++)
if(n%i==0)
{
int s=0;
while(n%i==0)
s++,n/=i;
//质因数分解,让所有的质数的指数全是偶数倍
if(s%2)res*=i;
}
if(n>1)res*=n;
cout<<res<<endl;
return 0;
}
第九题:负载均衡
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 200010;
int n, m;
int s[N];
priority_queue<PII, vector<PII>, greater<PII>> q[N];
//如果这里还不太清楚的话,就得去看一下优先队列的用法了哦!
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &s[i]);
while (m -- )
{
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
while (q[b].size() && q[b].top().x <= a)
{
s[b] += q[b].top().y;
q[b].pop();
}
if (s[b] < d) puts("-1");
else
{
q[b].push({a + c, d});
s[b] -= d;
printf("%d\n", s[b]);
}
}
return 0;
}
第十题:国际象棋
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, M = 1 << 6, K = 21, MOD = 1e9 + 7;
int n, m, k;
int f[N][M][M][K];
int get_count(int x)//计算二进制数中有多少个1
{
int res = 0;
while (x)
{
res ++ ;
x -= x & -x;
}
return res;
}
int main()
{
cin >> n >> m >> k;
f[0][0][0][0] = 1;
for (int i = 1; i <= m; i ++ )
for (int a = 0; a < 1 << n; a ++ )
for (int b = 0; b < 1 << n; b ++ )
{//a行不能与b行起冲突
if (b & (a << 2) || a & (b << 2)) continue;
for (int c = 0; c < 1 << n; c ++ )
{//b行不能与c行起冲突,a行也不能和c行起冲突
if (c & (a << 2) || a & (c << 2)) continue;
if (c & (b << 1) || b & (c << 1)) continue;
int t = get_count(b);
for (int j = t; j <= k; j ++ )
f[i][a][b][j] = (f[i][a][b][j] + f[i - 1][c][a][j - t]) % MOD;
}
}
int res = 0;
for (int a = 0; a < 1 << n; a ++ )
for (int b = 0; b < 1 << n; b ++ )
res = (res + f[m][a][b][k]) % MOD;
printf("%d\n", res);
return 0;
}