H. Horizon Scanning
- 这道题答案有单调性不假,可是也不是有单调性就一定要二分的吧?貌似直接取最小值就好了呀……
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
struct t1
{
double x,y;
double r;
}t[400005];
bool cmp(t1 a,t1 b)
{
return a.r<b.r;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>t[i].x>>t[i].y;
if(t[i].x>=0&&t[i].y>0)
{
t[i].r=pi/2-(atan(t[i].x/t[i].y));
}
else if(t[i].x<0&&t[i].y>=0)
{
t[i].r=pi-atan(-t[i].y/t[i].x);
}
else if(t[i].x<=0&&t[i].y<0)
{
t[i].r=pi+(pi/2-atan(t[i].x/t[i].y));
}
else if(t[i].x>0&&t[i].y<=0)
{
t[i].r=2*pi-atan(-t[i].y/t[i].x);
}
}
sort(t+1,t+n+1,cmp);
for(int i=1;i<n;i++)
{
t[i+n]=t[i];
t[i+n].r+=2*pi;
}
double l=0,r=2*pi;
int eps=100;
while(eps--)
{
double mid=(l+r)/2;
bool f=true;
for(int i=1;i<=n;i++)
{
auto check=[i,mid](t1 x)
{
return x.r-t[i].r<mid;
};
int p=partition_point(t+i,t+n+i,check)-1-t;
if(p-i<k)
{
f=false;
break;
}
}
if(f==true)
{
r=mid;
}
else
{
l=mid;
}
}
cout<<fixed<<setprecision(10)<<l<<"\n";
}
return 0;
}
L. Last Chance: Threads of Despair
- and each of his minions can attack any one minion from the opposing faction at most once. 是指每个己方势力总共只能攻击一次,而不是每个己方势力都可以攻击每个敌方势力各一次
- 引理:必然存在一种方案使得我方先进行所有攻击操作,此后不断发生爆炸直到对方所有单位清空
- 证明:如果一个操作方案中,在某次攻击之前发生过爆炸,那么我们将此次攻击移动到所有攻击之前,效果不变,同时也不会导致原本的其他操作失效
- 模拟一次攻击操作太麻烦了,有没有什么更简便的做法呢?当然有了,把己方健康值-1和敌方健康值-1分离。先把己方的攻击次数统一提取出来,再贪心地分配给敌方就好啦。
#include <bits/stdc++.h>
using namespace std;
int a[500005],b[500005],n,m;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
int tot=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
tot+=(a[i]>1);
}
sort(a+1,a+n+1);
tot+=(a[1]==1);
for(int i=1;i<=m;i++)
{
cin>>b[i];
}
sort(b+1,b+m+1);
int p=0,q=0,cur=0;
while(q<m)
{
while(p<n&&a[p+1]-1<=cur)
{
p++;
cur++;
}
if(b[q+1]>cur)
{
tot-=(b[q+1]-cur);
if(tot<0)
{
break;
}
}
q++;
cur++;
}
q==m? cout<<"Yes\n":cout<<"No\n";
}
return 0;
}
G. GCD
- 一开始没什么思路。午休的时候躺在床上想,
你精通GCD和各种动态规划,居然想不到做法,而且榜单上还能有200多个队伍过题,会不会答案是有限的,直接搜索就好了呢?一试,真的通过了!看来,根据榜单上的过题人数感受题目大致的做法,是一项远被之前的你低估的能力。大家其实也都不太会猜,你看学校的主力队伍交了快10次才在比赛即将结束的时候通过呢
#include <bits/stdc++.h>
using namespace std;
int ans,cur;
void solve(long long a,long long b)
{
if(cur>=ans)
{
return;
}
if(a==0)
{
ans=min(ans,cur+1);
return;
}
if(b%a==0)
{
ans=min(ans,cur+2);
return;
}
int g=__gcd(a,b);
cur++;
solve(a-g,b);
solve(a,b-g);
cur--;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
long long a,b;
cin>>a>>b;
ans=20;
cur=0;
solve(a,b);
cout<<ans<<"\n";
}
return 0;
}
C. Coin
- 倒序思考+数论分块,很轻松就解决啦~有什么难的呢?
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
long long n,k;
cin>>n>>k;
long long cur=k-1;
if(cur>=n)
{
cout<<n<<"\n";
continue;
}
else
{
while(cur+cur/(k-1)+(cur%(k-1)>0)<=n)
{
if(cur%(k-1)&&cur/(k-1)==(cur+cur/(k-1)+1)/(k-1))
{
long long cnt=min(n-cur,k-1-cur%(k-1))/(cur/(k-1)+1);
cur=cur+cnt*(cur/(k-1))+cnt;
continue;
}
cur=cur+cur/(k-1)+(cur%(k-1)>0);
}
cout<<cur<<"\n";
}
}
return 0;
}
- 原来所谓的金银牌分界题,也不过是个简简单单的高斯消元罢了~
#include <bits/stdc++.h>
using namespace std;
vector<int>a[305];
int c[305*305][305],tmp[305*305][305];
int n,m,k;
int q[305];
bool Gauss()
{
memcpy(tmp,c,sizeof(tmp));
for(int i=1;i<=n;i++)
{
for(int j=i;j<=m;j++)
{
if(c[j][i]>0)
{
swap(c[i],c[j]);
break;
}
}
if(!c[i][i])
{
return false;
}
q[i]=c[i][n+2];
for(int j=1;j<=m;j++)
{
if(i!=j&&c[j][i])
{
for(int k=1;k<=n;k++)
{
c[j][k]^=c[i][k];
}
}
}
}
memcpy(c,tmp,sizeof(c));
return true;
}
void Gauss(int n)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=j&&c[j][i])
{
for(int k=1;k<=n+1;k++)
{
c[j][k]^=c[i][k];
}
}
}
}
cout<<"!";
for(int i=2;i<=n;i++)
{
cout<<" "<<c[i][n+1];
}
cout<<endl;
}
int s[305];
void dfs(int n1,int dep,int fa)
{
s[dep]=n1;
if(dep==k)
{
m++;
c[m][0]=s[0];
for(int i=0;i<=k;i++)
{
c[m][s[i]]=1;
}
c[m][n+1]=s[k];
c[m][n+2]=m;
return;
}
for(int i=0;i<a[n1].size();i++)
{
if(a[n1][i]!=fa)
{
dfs(a[n1][i],dep+1,n1);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
m=1;
c[1][1]=1;
for(int i=1;i<=n;i++)
{
dfs(i,0,0);
}
if(Gauss())
{
cout<<"YES"<<endl;
cout<<"? "<<n-1;
for(int i=2;i<=n;i++)
{
cout<<" "<<c[q[i]][0]<<" "<<c[q[i]][n+1];
}
cout<<endl;
for(int i=2;i<=n;i++)
{
int w;
cin>>w;
c[q[i]][n+1]=w;
memcpy(tmp[i],c[q[i]],sizeof(tmp[i]));
}
memcpy(c,tmp,sizeof(c));
Gauss(n);
}
else
{
cout<<"NO"<<endl;
}
return 0;
}