2020牛客寒假算法基础集训营2
A min(A,Y)+min(B,Z)+min(C,X)
B
1 和 66 以外不需要考虑。
要让 616616 子串最多一定是 61616… ,这样后面的串可以继续接16 ,所以如果cnt6>cnt1 答案就是cnt1
else 就是cnt-1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
char s[N];
int main()
{
int n;
cin>>n;
getchar();
cin>>s;
//cout<<s<<endl;
int cnt1=0,cnt2=0;
for(int i=0;i<n;i++)
if(s[i]=='1') cnt1++;
else if (s[i]=='6') cnt2++;
int ans;
if(cnt1<cnt2) ans=cnt1;
else ans=cnt2-1;
cout<<ans;
return 0;
}
C 给出的概率p是以逆元的形式给出的,且1-p =(mod+1-p)直接运算就可以,和逆元并没有什么关系
dp就很好想了 dp[i][j] 表示前i道题对j道的概率(j<=i)那么第i道题只有两种情况:对与不对
如果对就要乘前i道对j-1的概率 如果不对就要乘前i道就已经对j道德概率
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2010,mod=1e9+7;;
ll s[N],dp[N][N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>s[i];
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
dp[i][0]=(dp[i-1][0]*(mod+1-s[i]))%mod;
for(int j=1;j<i;j++)
{
dp[i][j]=((dp[i-1][j-1])*(s[i])%mod+dp[i-1][j]*(mod+1-s[i])%mod)%mod;
}
dp[i][i]=(dp[i-1][i-1]*(s[i]))%mod;
}
for(int i=0;i<=n;i++)
cout<<dp[n][i]<<' ';
return 0;
}
D 直接暴力就可以了 需要注意钝角三角形的判定,首要条件是能形成三角形!!!
还有 万能头文件编译得太慢了 tle 太亏了
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=510,eps=1e-6;
int x[N],y[N],n;
bool check(int i,int j,int k)
{
int a[3];
a[0]=pow(x[i]-x[j],2)+pow(y[i]-y[j],2);
a[1]=pow(x[j]-x[k],2)+pow(y[j]-y[k],2);
a[2]=pow(x[i]-x[k],2)+pow(y[i]-y[k],2);
sort(a,a+3);
if(sqrt(a[0])+sqrt(a[1])>sqrt(a[2])&&a[2]>a[1]+a[0]) return 1;
else return 0;
}
int main()
{
int ans=0;
cin>>n;
for(int i=0;i<n;i++)
cin>>x[i]>>y[i];
for(int i=2;i<n;i++)
{
for(int j=1;j<i;j++)
{
for(int k=0;k<j;k++)
{
if(check(i,j,k)) ans++;
}
}
}
cout<<ans;
return 0;
}
E 打表可以发现只有完全平方数结果才会在上一个完全平方数的基础上增加 而且增加的数量等这个数的因子的对数;如果不是完全平方数,和上一个完全平方数保持一致
只用在在根号n的时间枚举完全平方数在枚举它的因子对数就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
int main()
{
int n;
ll ans=0;
cin>>n;
{
ans=0;
for(int i=1;i*i<=n;i++)
{
ll res=0,m=i*i;
for(int j=1;j*j<=m;j++)
if(m%j==0)
{
if(j*j==m) res++;
else res+=2;
}
ans+=res;
}
cout<<ans;
}
return 0;
}
F 每个物品有 a,b两个属性 一直你需要a属性,对手需要b属性,你拿了物品i,你得到了ai,而对手就得不到bi了 是不是就相当于对手减了bi,最后在计算差值时就要减-bi,负负得正等于 ai+bi(这是我想的…详细证明看标称吧 https://ac.nowcoder.com/discuss/364961?type=101&order=0&pos=13&page=3)。
所以对ai+bi排序就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
struct node
{
int a,b,c;
}e[N],d[N];
bool cmp(node x,node y)
{
return x.a>y.a;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>e[i].a,e[i].c=i;
for(int i=0;i<n;i++)
{
cin>>e[i].b;
e[i].a+=e[i].b;
}
sort(e,e+n,cmp);
vector<int> ve,ve1;
for(int i=0;i<n;i++)
{
if(i%2==0)
{
ve.push_back(e[i].c);
}
else ve1.push_back(e[i].c);
}
for(int i=0;i<ve.size();i++)
cout<<ve[i]+1<<' ';
cout<<endl;
for(int i=0;i<ve1.size();i++)
cout<<ve1[i]+1<<' ';
return 0;
}
G 我当时写的是如果g>0幂运算出现>g我就输出no了g<0同样得道理 虽然过了其实仔细想想 有正有负 还是不太严谨算是卡过去了 hhh
标称说的是多选几个模数提高正确率
H 标程说的不错嘿嘿
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300010,inf=0x3f3f3f3f;
int n,s[N],k,ans=0;
int dp[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>s[i];
sort(s+1,s+n+1);
for(int i=1;i<k;i++)
dp[i]=0x3f3f3f3f;//这里初始化为inf而不是-a1,因为前k个已经不可划分了必须一起释放 就不能在这里更新最小值了 初始化最大值不错
dp[k]=s[k]-s[1];
for(int i=k+1;i<=n;i++)
{
dp[i]=min(s[i]+dp[i-1]-s[i-1],dp[i-k]-s[i-k+1]+s[i]);
}
cout<<dp[n];
return 0;
}
I lowbit(x)返回x的最后一位1 等于 x&-x;
最开始以为要跑最小生成树 但是点太多时间复杂度太高 也就只能从异或和lowbit的性质入手了吧
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
int n,s[N],m,ans=0;
int main()
{
map<int,int> mp;
cin>>n;
m=n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
if(mp[s[i]]) m--;
mp[s[i]]++;
}
for(int i=0;i<=30;i++)
{
int res1=0,res2=0;
for(int j=1;j<=n;j++)
if((s[j]>>i)&1) res1++;
else if(((s[j]>>i)&1)==0) res2++;
if(res1>0&&res2>0)
{
cout<<(1ll*(1ll<<i)*(m-1));//防止爆int
break;
}
}
if(m==1) puts("0");
return 0;
}