蓝桥杯补题
知识点模块
1.x=(y2-z2),x=(y-z)*(y+z);说明x由两个奇偶性相同的数相乘而得
令y-z=a,y+z=b,消元一下得出2*y=(a+b),因为y为整数,所以a+b为偶数,所以a和b的奇偶性肯定是相同的
2.一个数由两个偶数相乘而得到
那么它一定是4的倍数
题解模块
P8635 [蓝桥杯 2016 省 AB] 四平方和
这题做过两次了,还有3个点超时,注意一下三层循环里要把i那层写成i * i<n,把j那层写成i*i+j * j<n,把k那层写成i * i+j * j +k * k<n
点击查看代码
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin>>n;
for(int i=0;i*i<n;i++)
{
for(int j=i;i*i+j*j<n;j++)
{
for(int k=j;i*i+j*j+k*k<n;k++)
{
int m=n-i*i-j*j-k*k;
int h=(int)sqrt(m);
if(h*h==m){
cout<<i<<" "<<j<<" "<<k<<" "<<h;
return ;
}
}
}
}
}
int main()
{
int t=1;
while(t--)
{
solve();
}
return 0;
}
P9231 [蓝桥杯 2023 省 A] 平方差
1.其实我们做题总是倾向于按照题目给的思路来,但真正的做题不是这样的,这就考察我们的思维和思考角度了这一题,具体看知识点1。
2.根据知识点1,我们可以得知当x为奇数时,x由1和它本身相乘而得,当x为偶数时,它由两个偶数构成,一个数的两个质因数都是偶数,那么这个数就是4的倍数
3.所以答案就是l和r之间,奇数的个数+4的倍数的个数
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> pii;
#define all(v) v.begin(),v.end()
typedef long long ll;
int j(int x)
{
if(!x) return 0;
else return (x+1)/2;
}
int o(int x)
{
return x/4;
}
void solve()
{
int l,r;
cin>>l>>r;
cout<<j(r)-j(l-1)+o(r)-o(l-1);
}
signed main()
{
int t=1;
//cin>>t;
while(t-- ) solve();
return 0;
}
P8605 [蓝桥杯 2013 国 AC] 网络寻路
1.先把每个点连接的图,画出来,每个点和多少个其他的点连接称为节点的度,联通的点固定一下路径,然后看这两个节点所连的其他节点有哪些,尝试枚举一下,其实其他节点就是度数-1。
2.以这个图为例子,我们固定1-2,那么与1连接的点有除2以外的3,4;那么则有4->1->2->3 , 4->1->3->2,那么实际上这样的路径就有(u的度数-1 * v的度数-1),由于是可以双向的,所以还要×2
3.所以开三个数组,d,u,v存度数,和每次的路线的两个点,然后按照上面公式算结果即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> pii;
#define all(v) v.begin(),v.end()
typedef long long ll;
int p[1005];
void solve()
{
int n,m;
cin>>n>>m;
int d[10005]={0},u[100005]={0},v[100005]={0};
for(int i=1;i<=m;i++){
cin>>u[i]>>v[i];
d[u[i]]++;
d[v[i]]++;
}
int ans=0;
for(int i=1;i<=m;i++)
{
ans+=(d[u[i]]-1)*(d[v[i]]-1)*2;
}
cout<<ans;
}
signed main()
{
int t=1;
//cin>>t;
while(t-- ) solve();
return 0;
}
P8604 [蓝桥杯 2013 国 C] 危险系数
1.要找关键点,其实一个点到另一个点的关键点,可以通过这个点被经过的次数,和总路径的次数比较,如果是相等的,那么就是关键点,可以画图出来理解
2.第一种方法就是简单的dfs遍历,寻找u和v间的总路径数,并统计每个点走过的次数,但是如果不会敲dfs就写不出来
3.第二种方法,是我的天才队友想出来的,可以通过并查集来解决,思路大概就是每次删除一个点以后,重新对所有的点找最终的父亲,如果说这个点被删了导致u和v的父亲不一样,那么这个点就是关键点,也就是删除点后再检查联通性
dfs的写法
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> pii;
#define all(v) v.begin(),v.end()
typedef long long ll;
int n,m,u,v,a[1005][1005],ans,sum;
int cnt[1005];
bool st[1005];
void dfs(int x)//x代表遍历的深度
{
if(x==v)
{
sum++;
for(int i=1;i<=n;i++) if(st[i]) cnt[i]++;
}else{
for(int i=1;i<=n;i++)
{
if(a[x][i]==1&&!st[i])
{
st[i]=1;
dfs(i);//搜索这个通的点
st[i]=0;
}
}
}
}
void solve()
{
cin>>n>>m;
while(m--)
{
cin>>u>>v;
a[u][v]=a[v][u]=1;
}
cin>>u>>v;
dfs(u);
if(sum>0){
for(int i=1;i<=n;i++)
{
if(cnt[i]==sum) ans++;
}
cout<<ans-1;
}else cout<<-1;
}
signed main()
{
int t=1;
//cin>>t;
while(t-- ) solve();
return 0;
}
并查集的写法
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> pii;
#define all(v) v.begin(),v.end()
typedef long long ll;
int n,m,ans;
int p[1005];
pii a[1005];
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
void solve()
{
//点是1 2 3 4 5 不是我们输入这个点对哈 不要理解成点对
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i].first>>a[i].second;
}
int u,v;
cin>>u>>v;
for(int i=1;i<=n;i++)
{
iota(p,p+n+1,0);
if(i==u||i==v) continue;
for(int j=1;j<=m;j++){
if(a[j].first==i||a[j].second==i) continue;//这个就是删除操作
int xx=find(a[j].first),yy=find(a[j].second);
p[xx]=yy;
}
//上面删完枚举的点以后 重新找了u和v的父亲
//删完以后如果u和v的父亲不一样了就是不联通了
if(find(u)!=find(v)) ans++;
}
cout<<ans;
}
signed main()
{
int t=1;
//cin>>t;
while(t-- ) solve();
return 0;
}
posted on 2024-05-30 18:20 swj2529411658 阅读(11) 评论(0) 编辑 收藏 举报