A题,找符合条件的三角形,脑抽想少了。
符合条件的三角形有许多种:
1.底为1,高为2,底与x轴平行
2.底为1,高为2,底与y轴平行
3.底为2,高为1,底与x轴平行
4.底为2,高为1,底与y轴平行
每种的计算只需要枚举高所经过的顶点即可,但是在边界处的直角三角形会计算重复,需要减去。还应注意:中间部分三角形的方向可以翻转,*2.
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 1e9 + 7;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
long long n, m;
cin >> n >> m;
long long sum = 0;
long long a,b;
a = (n-1)*(m-2) % mod;
a *= (n+m-2);
a %= mod;
b = (n-2)*(m-1) % mod;
b *= (n+m-2);
b %= mod;
sum = a+b % mod;
cout << 2*sum % mod << endl;
return 0;
}
B题水题,跳过
C题,可以算是个模拟加贪心
挡板只能放在x轴或者y轴之上,所以,只需要计算起点与所有靶子的横纵截距即可
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 50;
double x[maxn],y[maxn];
int numx = 0, numy = 0;
int main()
{
double x0,y0;
cin >> x0 >> y0;
int n, k;
cin >> n >> k;
for(int i = 0; i < n; i++)
{
long long x1,y1;
cin >> x1 >> y1;
if(x1*x0<0)
{
y[numy++] = y0-(1.0 *x0*(y0-y1))/(x0-x1);
}
if(y1*y0<0)
{
x[numx++]= x0-(1.0 *y0*(x0-x1))/(y0-y1);
}
}
if(n-numx>k&&n-numy>k)
{
cout << -1 << endl;
return 0;
}
sort(x,x+numx);
sort(y,y+numy);
int cnt = n - k;
double ans = 6000000009;
// cout << num << endl;
for(int i = 0; i + cnt - 1 < numx; i++)
{
ans = min(ans, x[i+cnt-1] - x[i]);
// cout << ans << endl;
}
//cout << ans << endl;
for(int i = 0; i + cnt - 1 < numy; i++)
{
ans = min(ans, y[i+cnt-1] - y[i]);
}
printf("%.9lf\n",ans);
return 0;
}
D题更加水了…
E题我使用的是算数基本定理(唯一分解定理)
根据对x的质因数分解来计算x的因数个数,按题意直接迭代即可。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e6 + 50;
int su[N] = {0};
long long zhi[N];
int z = 0;
int aishai()
{
su[1] = 1;
for(int i = 2; i <= 1e6 + 5; i++)
{
if(su[i] == 0)
{
zhi[z] = i;
z++;
for(int j = 2; j * i <= 1e6 + 5; j++)
{
su[i*j] = 1;
}
}
}
}
long long hanshu(long long a)
{
long long ans = 1;
long long n = a;
for(int i = 0; i < z && zhi[i] <= a; i++)
{
if(a % zhi[i] == 0)
{
long long cnt = 0;
while(a % zhi[i] == 0)
{
a /= zhi[i];
cnt++;
}
ans *= (1 + cnt);
}
}
if(a > 1)
ans *= 2;
return ans;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
aishai();
long long n;
cin >> n;
long long ans = 1,t;
while( (t = hanshu(n)) != 2)
{
ans++;
n = t;
}
cout << ans << endl;
return 0;
}
G题,暴力
记录每一种字母出现的位置,之后遍历所有字母,每次只取k个字母的间距,记录最小值即可。
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 50;
int a[27][maxn],b[27];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, k;
cin >> n >> k;
string s;
cin >> s;
for(int i = 0; i < n; i++)
{
a[s[i]-'a'][b[s[i]-'a']++] = i;
}
int ans = maxn;
for(int i = 0; i <= 'z' - 'a'; i++)//遍历所有字母
{
for(int j = 0; j+k <= b[i]; j++)
{
ans = min(ans, a[i][j+k-1] - a[i][j] + 1);
}
}
if(ans == maxn)
cout << -1 << endl;
else
cout << ans << endl;
return 0;
}
H题套的尺取法模板,学会之后,一定滚回来更新代码。