2020牛客寒假算法基础集训营1

直接放题的链接算啦 这题粘贴会有图片上传很容易失效0.0.

honoka和格点三角形
 

题目描述

honoka最近在研究三角形计数问题。
她认为,满足以下三个条件的三角形是“好三角形”。
1.三角形的三个顶点均为格点,即横坐标和纵坐标均为整数。
2.三角形的面积为1 。
3.三角形至少有一条边和 x轴或y 轴平行。
honoka想知道,在平面中选取一个大小为 的矩形格点阵,可以找到多少个不同的“好三角形”?由于答案可能过大,请对1e9+7 取模。

输入描述:

两个正整数n和m(2 ≤n,m≤109)( 2\ ≤n,m≤10^9)(2 ≤n,m≤109)

输出描述:

面积为1的格点三角形的数量,对 109+7 取模的结果。

示例1

输入

2 3

输出

6

说明

格点如下:

*  *  *

*  *  *

不妨设左下角坐标为(1,1),右上角坐标为到(3,2)。
那么三点坐标可选:
(1,1)(1,2)(3,1)
(1,1)(1,2)(3,2)
(1,1)(2,2)(3,1)
(1,1)(3,1)(3,2)
(1,2)(2,1)(3,2)
(1,2)(3,1)(3,2)
所以共有6个。

示例2

输入

100 100

输出

7683984

说明

这里太小写不下啦。

这一题是算是找规律的题,也可以说是通过暴力的方法找寻规律,根据两种方法进行找寻规律,第一种三角形就是直角三角形,也就是两边分别跟x轴y轴平行的三角形,然后这种三角形的个数为4*(n-1)*(m-2)+4*(n-2)*(m-1),另一种三角形就是两边不平行的三角形;

AC代码如下

#include <bits/stdc++.h>
using namespace std;
long long sum=0,n,m;
long long mod=1e9+7;
int main()
{
	cin>>n>>m;
	sum=(4*(n-1)*(m-2)%mod+4*(m-1)*(n-2)%mod)%mod;
	sum=(2*(n-2)*(m-2)%mod*(m-1)%mod+sum)%mod+(2*(m-2)*(n-2)%mod*(n-1))%mod;
	sum=(sum%mod+2*(m-2)*(m-2)%mod*(n-1)%mod)+(2*(m-1)*(n-2)%mod*(n-2)%mod);
	cout<<sum%mod<<endl;
}
B

kotori和bangdrea 

打卡题 代码如下

 

https://ac.nowcoder.com/acm/contest/3002/B

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n,a,x,b;
	double sum;
	scanf("%d %d %d %d",&n,&x,&a,&b);
	sum=n*x*a+b*(100-x)*n;
	sum=sum*0.01;
	printf("%.2lf",sum);
}
Dhanayo和米饭

 https://ac.nowcoder.com/acm/contest/3002/D

 打卡题,两次排序比较输出就好了

代码如下

#include <bits/stdc++.h>
using namespace std;
int a[100000+10],b[100000+10];
int main()
{
	int n;
	cin>>n;
	memset(a,0,sizeof(a));
	for(int i=1;i<n;i++)
	{
		cin>>a[i];
		b[i]=i;
	}
	sort(a+1,a+n);
	for(int i=1;i<=n;i++)
	{
		if(a[i]!=b[i])
		{
			cout<<b[i]<<endl;
			return 0;
		}
	}
}
Erin和快速迭代

https://ac.nowcoder.com/acm/contest/3002/E

只要统计因子的个数,然后跟着题意写就可以了,然后要记着开longlong 我第一次没开longlong就错误了. 

代码如下

#include <bits/stdc++.h>
using namespace std;
int count(long long n)///求因子的个数
{
    int s=1;///记录总共的素因子的个数
    for(int i=2;i*i<=n;i++)
        if(n%i==0)
    {
        int a=0;///记录的是每个素因子的个数
        while(n%i==0)
        {
            n/=i;
            a++;
        }
        s=s*(a+1);
    }
    if(n>1)
        s=s*2;
    return s;
}
int main()
{
	long long x,sum=0;
	cin>>x;
	while(x!=2)
	{
		x=count(x);
		sum++;
	}
	cout<<sum<<endl;
}
Geli和字符串

 https://ac.nowcoder.com/acm/contest/3002/G

开一个26个英文字母的前缀和数组,然后对每一个字母进行统计,然后要用双指针对这个数组进行标记处理,一点一点的双指针移动动态更新长度就好了

代码如下

#include<bits/stdc++.h>
using namespace std;
int dp[200010][26]={0};     //26个前缀和数组
int main(){
    int n,k,i,j;
    cin>>n>>k;
    string s;
    cin>>s;
    dp[0][s[0]-'a']=1;
    for(i=1;i<n;i++){
        for(j=0;j<26;j++){
            dp[i][j]=dp[i-1][j];
        }
        dp[i][s[i]-'a']++;
    }
    int mi=1e9;
    for(i=0;i<26;i++){
        int temp=0,t2=0;
        if(dp[n-1][i]<k)continue;
        while(temp<n&&dp[temp][i]==0)temp++;
        while(t2<n&&dp[t2][i]<k)t2++;
        mi=min(mi,t2-temp+1);
        for(temp++;temp<n;temp++){
 
            if(s[temp-1]-'a'==i){
                t2++;
                while(t2<n&&s[t2]-'a'!=i)t2++;
                if(t2==n)break;
            }
            mi=min(mi,t2-temp+1);
        }
    }
    if(mi==1e9)cout<<-1;
    else cout<<mi;
}
Hnozomi和字符

 

 https://ac.nowcoder.com/acm/contest/3002/H

存储0和1字符的位置,进行暴力的求解,分别对1和0进行k的操作,求出来最长的串。

代码如下

#include<bits/stdc++.h>
using namespace std;
string s;
vector<int>v0,v1;       //v0存字符'0'的坐标位置,v1存字符'1'的坐标位置
int main(){
  
    int n,k,i,j;
    cin>>n>>k;
    cin>>s;
    v0.push_back(-1);
    v1.push_back(-1);
    for(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 ma=0;
    if(v0.size()-2<=k)ma=n;
    else{
        for(i=1,j=k;j<v0.size()-1;i++,j++){
            ma=max(ma,v0[j+1]-v0[i-1]-1);
        }
    }
    if(v1.size()-2<=k)ma=n;
    else{
        for(i=1,j=k;j<v1.size()-1;i++,j++){
            ma=max(ma,v1[j+1]-v1[i-1]-1);
        }
    }
    cout<<ma;
}
Inico和niconiconi

https://ac.nowcoder.com/acm/contest/3002/I

进行dp解题,设置一个数组dp【i】,i代表着扫描字符串是这个位置上目前的最大值,然后要注意三个状态转移方程

dp[i]=max(dp[i],dp[i-3]+a)

dp[i]=max(dp[i],dp[i-5]+b)

dp[i]=max(dp[i],dp[i-9]+c)

之后就好写了;

代码如下

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[300000+10]={0};
string ss;
int main()
{
	int n,a,b,c;
	cin>>n>>a>>b>>c>>ss;
	for(int i=0;i<n;i++)
	{
		if(i>0)
		{
			dp[i]=dp[i-1];
		}
		if(i>=3&&ss[i-3]=='n'&&ss[i-2]=='i'&&ss[i-1]=='c'&&ss[i]=='o')
		{
			dp[i]=max(dp[i],dp[i-3]+a);
		}
		if(i>=5&&ss[i-5]=='n'&&ss[i-4]=='i'&&ss[i-3]=='c'&&ss[i-2]=='o'&&ss[i-1]=='n'&&ss[i]=='i')
		{
			dp[i]=max(dp[i],dp[i-5]+b);
		}
		if(i>=9&&ss[i-9]=='n'&&ss[i-8]=='i'&&ss[i-7]=='c'&&ss[i-6]=='o'&&ss[i-5]=='n'&&ss[i-4]=='i'&&ss[i-3]=='c'&&ss[i-2]=='o'&&ss[i-1]=='n'&&ss[i]=='i')
		{
			dp[i]=max(dp[i],dp[i-9]+c);
		}
	}
	cout<<dp[n-1];
}

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值