—>XJOI奋斗群(蒻蒟群)群赛3<— RANK排名7
T1:Kirill And The Game(TLE一次后AC)
题意:
给你两个区间l到r,x到y,让你求在这个区间中是否存在两个数a,b,使得a在第一个区间中,b在第二个区间中,并且a/b的值为给出的数k。
分析过程:
刚开始想都没想就写了两个for循环,计算每个k的值,再去进行比较,果断TLE。然后思考了一下,发现这题根本不用这样做,只要列举第二个区间的所有整数,再乘k,看是否有乘积落在第一个区间中,如果有,就输出YES,反之输出NO,这样还省的用double。
给出题解:
#include<bits/stdc++.h>
using namespace std;
int main()
{
bool flag=false;
long long int l,r,x,y,xiaolv,k;
cin>>l>>r>>x>>y>>k;
for(int i = x; i <= y ; i++)
{
xiaolv =i*k;
if(xiaolv>=l&&xiaolv<=r){flag=true;break;}
}
if(flag==true)cout<<"Yes";
else cout<<"No";
}
T2:Gleb And Pizza(WA一次后AC)
题意:
给你一个披萨,整个半径为r,外面壳的半径为d。披萨的圆心再原点上。然后披萨上面有一些圆形的香肠片,给出每个香肠片的圆心的坐标和半径,问你有几个香肠片是完全在壳上的。
分析过程:
刚开始以为这题就只是需要模拟一下就行了。可是交了一次才发现这题数据是有多么的坑。首先是d的值,给出的数据中,可能会出现d的值是0的情况,然而这个时候并不是指这个披萨是没有壳的,而是指这个披萨的壳就是紧紧的贴在内圆上的(净扯!)。然后是香肠片的半径,同样也会出现值为0的情况,与壳相同,这并不是指不存在这个香肠片了,而是这个香肠片是个点(又扯!)。所以只要把这些特殊的数据加以处理一下,其他的都比较简单。还有就是我的代码里没用sqrt,毕竟数据比较大,还有100个测试点,怕是要TLE。
给出题解:
#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
int get_dis(int x,int y)
{
int dis=x*x+y*y;
return dis;
}
int main()
{
int r1,r2;
int n;
int x[maxn],y[maxn],r[maxn];
int dis,dis2,dis3;
int cnt=0;
cin>>r1>>r2>>n;
if(r2!=0)
{
r2=r1-r2;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i]>>r[i];
dis=get_dis(x[i],y[i]);
dis2=(r1-r[i])*(r1-r[i]);
dis3=(r2+r[i])*(r2+r[i]);
if(dis<=dis2&&dis>=dis3)cnt++;
}
}
else
{
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i]>>r[i];
if(r[i]==0)
{
dis=get_dis(x[i],y[i]);
if(dis==r1*r1)cnt++;
}
}
}
cout<<cnt;
}
T3:Ilya And The Tree (已AC)
题意:
给出一棵生成树,每个节点都有一个值,现在要求出每个节点的美丽值的最大值,美丽值的定义为从根节点到该节点(包含)路径上所有点的值的gcd,求解每个点时可以把路径上某一个点的值变为0。你可以认为每个点美丽值的求解是独立的。
分析过程:
可以用树形DFS,我们用dp数组来保存每个节点在路径上没有改变值的时候的gcd,然后先单独考虑当前点不选的美丽值即dp[u]。然后用vector[u]数组来保存节点v的父亲节点的美丽值的所有可能情况,这里的情况有可能是改变了值后的,也可能没有,但由于我们在这一步一定会算入节点v的值(不算的情况单独考虑),所以满足最多只改变一次值的要求。
给出题解:
#include<bits/stdc++.h>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
typedef long long ll;
const int maxn = 200005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int n,cnt;
int a[maxn],dp[maxn];
int head[maxn];
vector<int>vec[maxn];
struct node
{
int v,next;
}e[maxn*2];
void add(int u,int v)
{
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int u,int pre)
{
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==pre) continue;
dp[v]=gcd(dp[u],a[v]);
vec[v].push_back(dp[u]);
for(int i=0;i<vec[u].size();i++)
{
vec[v].push_back(gcd(vec[u][i],a[v]));
}
sort(vec[v].begin(),vec[v].end()); //????
vec[v].erase(unique(vec[v].begin(),vec[v].end()),vec[v].end());
dfs(v,u);
}
}
int main()
{
// freopen("in.txt","r",stdin);
mst(head,-1);
cnt=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int x,y;
for(int i=0;i<n-1;i++)
{
cin>>x>>y;
add(x,y);
add(y,x);
}
dp[1]=a[1];
vec[1].push_back(0);
dfs(1,-1);
for(int i=1;i<=n;i++)
{
dp[i]=max(dp[i],vec[i].back());
}
for(int i=1;i<n;i++)
{
cout<<dp[i]<<" ";
}
cout<<dp[n];
return 0;
}
T4:Mike and gcd problem (WA两次后AC)
题意:
给你一个串数列,你可执行的操作便是选出a[i]和a[i+1]这两个数,分别用a[i]-a[i+1]和a[i]+a[i+1]替换。操作到最后,让这个数列的最大公约数大于1。如果可以的话,输出YES和需要的步数,如果不行,就输出NO。
分析过程:
这题如果想出了方法就比较简单了。既然是要最大公约数大于1,那么最容易达到的肯定就是2了,因为2的倍数多的要命啊。而且两个奇数只需一次上述操作就可以变成两个偶数,而一奇一偶则只需两次操作就可以变成两个偶数,所以让最大公约数变成2应该是最快的。然后就是怎么变了,刚开始没有看到这两个数必须是相邻的数,只是简简单单的判断了一下奇数的个数,来算最少的步骤,结果在第4个点就WA了,然后改正之后,又是少特判的0这个东西。当所有的数都为0时,是不可能达成最大公约数大于1的情况的。最后改正过来后成功AC。不过还需注意的是负数和正数的最大公因数,只需要吧这个负数当成正数看就行了。
给出题解:
#include<bits/stdc++.h>
using namespace std;
int get_gcd(int a,int b)
{
if(a!=0&&b!=0)
{
a=abs(a);
b=abs(b);
int m=min(a,b);
for(int i=m;i>=1;i--)
if(a%i==0&&b%i==0)return i;
}
if(a==0||b==0)return max(a,b);
}
int main()
{
bool flag=false;
int n,cnt=0,gcd,ans=0,t;
int a[100010];
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]!=0)flag=true;
}
if(flag==true)
{
for(int i=2;i<=n;i++)
{
if(i==2)gcd=get_gcd(a[1],a[i]);
else gcd=get_gcd(gcd,a[i]);
}
if(gcd!=1)cout<<"YES"<<endl<<0;
else
{
for(int i=1;i<n;i++)
if(a[i]%2==1&&a[i+1]%2==1)
{
cnt++;
t=a[i];
a[i]=t-a[i+1];
a[i+1]=t+a[i+1];
}
for(int i=1;i<n;i++)
{
if(a[i]%2==0&&a[i+1]%2==1)
{
cnt=cnt+2;
t=a[i];
a[i]=t-a[i+1];
a[i+1]=t+a[i+1];
t=a[i];
a[i]=t-a[i+1];
a[i+1]=t+a[i+1];
}
else if(a[i]%2==1&&a[i+1]%2==0)
{
cnt=cnt+2;
t=a[i];
a[i]=t-a[i+1];
a[i+1]=t+a[i+1];
t=a[i];
a[i]=t-a[i+1];
a[i+1]=t+a[i+1];
}
}
cout<<"YES"<<endl<<cnt;
}
}
else cout<<"NO";
return 0;
}
蒻蒟总结:
今天的群赛感觉有思路的题都能够A掉,但剩余的两题在比赛时感觉比较难,订正时也比较吃力,正在极力的订正中,所以第3、5题就先不发题解了,下一次发博客的时候再补回来。这两题都是我不怎么擅长的深搜,建树等等的,所以一旦有时间,就抓紧去补吧。