C. Fly
二分燃料重量,由于只有1000个星球,每次判断的时候直接模拟一遍这个过程即可。
二分浮点数的时候本应该格外小心精度,然而以前不少题没有格外注意也AC了,于是思想逐渐麻痹orz,于是这次挂了。
谨记……膨胀真可怕.jpg
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<iostream>
#include<algorithm>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n;
double m;
double a[maxn],b[maxn];
bool judge(double x)
{
double sum=m+x;
for(int i=1;i<=n;i++)
{
double tmp=sum/a[i];
sum-=tmp;
if(sum<=m)return false;
tmp=sum/b[i+1];
sum-=tmp;
if(m-sum>eps)return false;
}
return true;
}
int main()
{
scanf("%d%lf",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&a[i],&b[i]);
a[n+1]=a[1],b[n+1]=b[1];
double l=0,r=2000000000,ans=-1;
for(int i=0;i<100;i++)
{
double mid=l+(r-l)/2;
if(judge(mid))r=mid,ans=mid;
else l=mid;
}
if(ans==-1||ans-1000000000>eps)printf("-1\n");
else printf("%.8lf\n",ans);
return 0;
}
E. Border
给出n个数,问这n个数的线性组合能覆盖0-k中的哪些数。
如果只使用其中一个数ai,那么可以发现所能覆盖的数就是tmp=gcd(ai%k,k)的倍数。
如果使用多个数的线性组合,所覆盖的数就是tmp=gcd(a1%k,a2%k,...,an%k)的倍数。
为了减少不必要的重复覆盖,对tmp判重,此外还要单独考虑%k为0的情况。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<iostream>
#include<algorithm>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,k;
int a[maxn];
bool vis[maxn];
map<int,int>mo;
int gcd(int a,int b)
{
if(b==0)return a;
return gcd(b,a%b);
}
int main()
{
scanf("%d%d",&n,&k);
mo.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]%=k;
}
int tmp=a[1];
for(int i=2;i<=n;i++)
if(a[i]!=0)tmp=gcd(tmp,a[i]);
if(tmp==0)vis[0]=0;
else
{
for(int i=0;i<k;i+=tmp)
vis[i]=1;
}
if(tmp!=1)
{
mo[tmp]=1;
for(int i=1;i<=n;i++)
{
if(a[i]==0)
{
vis[0]=1;
continue;
}
tmp=gcd(a[i],k);
if(!mo[tmp])
{
mo[tmp]=1;
for(int j=0;j<k;j+=tmp)
vis[j]=1;
}
if(tmp==1)break;
}
}
int ans=0;
for(int i=0;i<k;i++)
if(vis[i])ans++;
printf("%d\n",ans);
int cnt=1;
for(int i=0;i<k;i++)
{
if(vis[i]){
printf("%d",i);
if(cnt==ans)printf("\n");
else printf(" ");
cnt++;}
}
return 0;
}