A - honoka和格点三角形
传送
题意:N*M大小的格点 可以组成多少面积大小为1且顶点在格点上的三角形;
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
int main()
{
long long n,m,ans=0;
cin>>n>>m; //局部代替整体
ans=(ans+(m-2)*(n-1)*4%mod +(n-2)*(m-1)*4%mod)%mod; //两条边都平行于坐标轴
ans=(ans+2*(m-2)*(m-2)%mod*(n-1)%mod+2*(n-2)*(n-2)%mod*(m-1)%mod)%mod; //一条边平行(底为2高1)
ans=(ans+2*(m-1)*(m-2)%mod*(n-2)%mod+2*(n-1)*(n-2)%mod*(m-2)%mod)%mod;//一条边平行(底为1高2)
cout<<ans<<endl;
return 0;
}
C - umi和弓道
传送
题解:分别求出两点之间与坐标轴的交点(如果存在的话),然后双指针遍历两个坐标轴维护最小值,只要某一条轴能挡住n-k个点就能成功;
#include<bits/stdc++.h>
using namespace std;
int main()
{
double X,Y;
cin>>X>>Y;
int n,k;
cin>>n>>k;
k=n-k; //有一点小绕
double x,y,num=0;
vector<double> vx,vy;
for(int i=0;i<n;i++){
cin>>x>>y;
// double kk = (Y-y)/(X-x); //解法一
// if(x*X>0&&y*Y>0) num++;
// else if(X==x) vx.push_back(x);
// else if(Y==y) vy.push_back(y);
// else if(X*x>0&&Y*y<0) vx.push_back(-y/kk+x);
// else if(X*x<0&&Y*y>0) vy.push_back(kk*(-x)+y);
// else {
// vx.push_back(-y/kk+x);
// vy.push_back(kk*(-x)+y);
// }
if(X*x<0) vy.push_back(y-x*(Y-y)/(X-x)); //解法二
if(Y*y<0) vx.push_back(x-y*(X-x)/(Y-y));
}
double ans=1e18;
sort(vx.begin() ,vx.end() );
sort(vy.begin() ,vy.end() );
for(int i=0,j=k-1;j<vx.size() ;i++,j++){
ans = min(vx[j] - vx[i],ans);
}
for(int i=0,j=k-1;j<vy.size() ;i++,j++){
ans = min(vy[j] - vy[i],ans);
}
if(ans==1e18) printf("-1\n"); //不管x轴还是y轴,只要能挡住n-k个点 就算成功了;
else printf("%.8lf\n",ans);
return 0;
}
F - maki和tree
传送门
主要在于理解题意,和建立模型;
计数:ans += x1+x2+x3+x2x1+x3(x1+x2) ;
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5+7;
char s[N];
vector<int> G[N];
LL ans=0,num=0;
void DFS(int p,int fa)
{
if(s[p]=='B') return ;
num++;
for(int i=0;i<G[p].size() ;i++)
if(G[p][i]!=fa) DFS(G[p][i],p);
}
int main()
{
int n ;
scanf("%d",&n);
int c = n;
scanf("%s",s+1);
while(--c){
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1;i<=n;i++){
LL A=0;
if(s[i]=='B'){
for(int j=0;j<G[i].size() ;j++){
num=0;
DFS(G[i][j],0);
ans+=A*num+num;
A+=num;
}
}
}
cout<<ans<<endl;
return 0;
}
H - nozomi和字符串
传送
题解:贪心,将01字符串分离成0串和1串(处理时将开头置为-1,末尾置为n),分别双指针求区间长度为k的最大值;
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,k;
cin>>n>>k;
vector<int> v0,v1;
string s;
cin>>s;
v0.push_back(-1);v1.push_back(-1);
for(int i=0;i<n ;i++)
if(s[i]=='0') v0.push_back(i);
else v1.push_back(i);
v0.push_back(n),v1.push_back(n);
int ans=0,num0 = v0.size() ,num1 = v1.size() ;
if(num0-2<=k||num1-2<=k) ans=n; //必不可少,k过大时不会进入循环;
for(int i=1,j=k;j<num0-1 ;i++,j++)
ans = max(ans , v0[j+1]-v0[i-1]-1);
for(int i=1,j=k;j<num1-1 ;i++,j++)
ans = max(ans , v1[j+1]-v1[i-1]-1);
cout<<ans<<endl;
return 0;
}
I - nico和niconiconi
传送
题解:简单动态规划;
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL n,a,b,c,dp[300010];
int main()
{
cin>>n>>a>>b>>c;
getchar();
string s;
getline(cin,s);
for(int i=0;i<n;i++){
dp[i+1] = dp[i];
if(i>=3 && s.substr(i-3,4)=="nico")
dp[i+1] = max(dp[i+1],dp[i-3]+a);
if(i>=5 && s.substr(i-5,6)=="niconi" )
dp[i+1] = max(dp[i+1],dp[i-5]+b);
if(i>=9 && s.substr(i-9,10)=="niconiconi")
dp[i+1] = max(dp[i+1],dp[i-9]+c);
}
cout<<dp[n]<<endl;
return 0;
}