补题ing
A. Bovine Dilemma
题目传送门:
思路:
只要暴力找到有多少长度不同的三角形底即可
AC Code
#include<bits/stdc++.h>
using namespace std;
int x[100];
int ans[100];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&x[i]);
int num=0;
memset(ans,0,sizeof(ans));
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(ans[x[j]-x[i]]==0)
{
ans[x[j]-x[i]]=1;
num++;
}
}
}
printf("%d\n",num);
}
//system("pause");
return 0;
}
B. Last minute enhancements
题目传送门:
思路:
简单模拟即可,如果当前数已经出现过,那就加一,记录每个出现过的数。
AC Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int num=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]>ans)
{
ans=a[i];
num++;
}
else if(a[i]==ans)
{
ans++;
num++;
}
}
printf("%d\n",num);
}
//system("pause");
return 0;
}
C. Canine poetry
题目传送门:
思路:
题目不想任何回文子串的存在。那么我们想到一个大的回文串必然存在小的回文串构成。那么我们就可以处理形如每个aa的第二个字符,aba的第三个字符,aaa的第二、三个字符即可。
AC Code
#include<iostream>
#include<string>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
int n = str.size();
int ans = 0;
for (int i = 0;i < n;i++)
{
if (str[i] == '#')continue;
if ( i + 2 <= n - 1&&str[i] == str[i + 2] )
{
ans++;
str[i+2] = '#';
}
if ( i + 1 <= n - 1&&str[i] == str[i + 1])
{
ans++;
str[i + 1] = '#';
}
}
cout << ans << endl;
}
}
D. 13th Labour of Heracles
题目传送门:
思路:
贪心的想如果一个点的度为n(大于1),那么代表这个点可以多涂(n-1)次颜色,那么每次颜色数量+1的时候,我们就找权值最大的且能涂的点即可。
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int ans[N],f[N];
int num;
LL w[N];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
LL sum=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&w[i]);
sum=sum+w[i];
}
num=0;
memset(ans,0,sizeof(ans));
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
ans[u]++;
ans[v]++;
if(ans[u]>=2) f[++num]=w[u];
if(ans[v]>=2) f[++num]=w[v];
}
sort(f+1,f+1+num,cmp);
for(int i=1;i<n;i++)
{
if(i==1) printf("%lld ",sum);
else
{
sum=sum+f[i-1];
printf("%lld ",sum);
}
}
printf("\n");
}
//system("pause");
return 0;
}
E. Apollo versus Pan(好题)
(数学,思维,按位运算)
题目传送门:
思路:
最直接的想法当然是暴力,那么n3的复杂度显然是会炸的,别说是n3了,就算是n2也是灰会炸的。那么我们就想到大概率应该对每个数的每一位有一个预处理的操作。我们先将公式变化一下:
到
那么显然问题就转化成了两个中括号中的数该怎么求。我们必然需要枚举每一个j,那么对于第j个数的第i位来说如果当前位是1,那么在与的操作中只有第i位同样是1的数才能贡献2i,在或的操作中只有第i为是0的数,我才能多贡献出2i,我们只要预处理出每一位的1有多少个数即可,那么答案就呼之欲出了。
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e5+10;
const LL mod=1e9+7;
LL num[75];
LL a[N],cnt[75];
LL quick_pow(LL a,LL b)
{
LL res=1;
while(b)
{
if(b%2) res=res*a%mod;
a=a*a%mod;
b=b/2;
}
return res%mod;
}
int main()
{
int t;
scanf("%d",&t);
for(int i=0;i<=63;i++)
cnt[i]=quick_pow(2,i);
while(t--)
{
memset(num,0,sizeof(num));
int n;
scanf("%d",&n);
LL ans=0;
for(int i=1;i<=n;i++)
{
LL x;
scanf("%lld",&x);
ans=(ans+x)%mod;
a[i]=x;
int k=0;
while(x)
{
if(x%2) num[k]++;
k++;
x=x/2;
}
}
LL sum=0;
for(int i=1;i<=n;i++)
{
LL f1=0,f2=ans;
LL x=a[i];
int k=0;
while(x)
{
if(x%2==1)
{
f1=(f1+cnt[k]*num[k]%mod)%mod;
f2=(f2+cnt[k]*(n-num[k])%mod)%mod;
}
k++;
x=x/2;
}
sum=(sum+f1*f2%mod)%mod;
}
printf("%lld\n",sum);
}
//system("pause");
return 0;
}
F. Euclid’s nightmare(好题)
(思维,并查集)
题意:
这道题的题目比较难读,我也是看了别人的题解才知道这题是什么意思(本人老菜b了)。Z2的定义是一个模2加法。给你一些向量,要你求出最少需要哪些向量,能组合出最多的不同向量。
思路:
一个向量最多两维是1,我们可以考虑并查集。对于一个向量,如果这个向量中为1的两维没有在一个连通分量里面,表示这个向量是最小覆盖中的向量,并把这个向量中的1的两维连在一起。同时,如果这个向量中的两维已经在一个连通分量里面了,表示这个向量可以由之前的不同向量相加而成。有的向量只有1维为1,我们对这个向量增加一维,进行增广,让这个向量的m+1维为1,就可以用并查集了。本人觉得这个模型还特别像线性代数中的向量的极大无关组,也许学过线代的朋友会有同样的感觉。
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e5+10;
const LL mod=1e9+7;
int fa[N];
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
queue<int>que;
bool Union(int x,int y)
{
int dx=find(x);
int dy=find(y);
if(dx==dy) return false;
else
{
fa[dx]=dy;
return true;
}
}
LL quick_pow(LL x,LL y)
{
LL res=1;
while(y)
{
if(y%2) res=res*x%mod;
x=x*x%mod;
y=y/2;
}
return res;
}
int num=0;
int main()
{
int n,m; //向量的个数和向量的维数
scanf("%d%d",&n,&m);
for(int i=1;i<=m+1;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
{
int k;
scanf("%d",&k);
int a,b;
if(k==1)
{
scanf("%d",&a);
if(Union(a,m+1))
{
que.push(i);
num++;
}
}
else
{
scanf("%d%d",&a,&b);
if(Union(a,b))
{
que.push(i);
num++;
}
}
}
printf("%lld %d\n",quick_pow(2,num),num);
while(!que.empty())
{
printf("%d ",que.front());
que.pop();
}
printf("\n");
//system("pause");
return 0;
}