前几把天天坐牢,心态炸裂,3场掉了200+。
PS:(零点战神打破魔咒,真不容易)
A. Integer Moves(摸你/分类讨论)
我们发现答案必然<=2,因此只需分类即可
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll a[Ma];
int main()
{
ll tt;
scanf("%lld",&tt);
while (tt--)
{
ll x,y;
scanf("%lld%lld",&x,&y);
ll ans=x*x+y*y;
ll p=sqrt(ans);
if (ans==0)
printf("0\n");
else if (p*p==ans)
printf("1\n");
else
printf("2\n");
}
return 0;
}
B. XY Sequence(摸你)
只需保证局部最优即可
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll a[Ma];
int main()
{
ll tt;
scanf("%lld",&tt);
while (tt--)
{
ll n,ma,x,y;
scanf("%lld%lld%lld%lld",&n,&ma,&x,&y);
ll ans=0;
for (ll i=1;i<=n;i++)
{
if (a[i-1]+x>ma)
a[i]=a[i-1]-y;
else
a[i]=a[i-1]+x;
ans+=a[i];
}
printf("%lld\n",ans);
}
return 0;
}
C. Bracket Sequence Deletion(摸你/分类讨论)
我们可以发现一共有4种情况:
(),)),((,)(,对于前3种直接结束,对于第4种,回文串格式变为了)((((....(((),因此摸你即可
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll n;
string s;
void sol()
{
ll add=0,f=0;
while (f+1<s.size())
{
if (s[f]=='(')
add++,f+=2;
else if (s[f+1]==')')
add++,f+=2;
else
{
ll flag=0;
for (ll i=f+2;i<s.size();i++)
{
if (s[i]==')')
{
add++,flag=1;
f=i+1;
break;
}
}
if (!flag)
break;
}
}
ll w=s.size()-f;
printf("%lld %lld\n",add,w);
return;
}
int main()
{
ll tt;
scanf("%lld",&tt);
while (tt--)
{
cin>>n>>s;
sol();
}
return 0;
}
D. For Gamers. By Gamers.(筛+二分答案)
首先我们发现问题变为花费k*ci,可以得到k*hi*di的贡献,因此变成了dp,而根据优化可以保证O(n*lnC)的dp。
我是根据离线算法O(n*lnC*logm)进行(以贡献为维度),事实上可以用在线算法(以花费为维度)进行,复杂度为O(n*lnc+m*logC)
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
struct node
{
ll c,w;
bool operator <(const node &A)const{
if (c==A.c)
return w>A.w;
return c<A.c;
}
}t[Ma];
struct que
{
ll num,w,ans;
bool operator <(const que &A)const{
return w<A.w;
}
}a[Ma];
bool cmp(que x,que y)
{
return x.num<y.num;
}
ll pp[Ma];
int main()
{
ll n,C;
scanf("%lld%lld",&n,&C);
for (ll i=1;i<=n;i++)
{
ll H,D;
scanf("%lld%lld%lld",&t[i].c,&H,&D);
t[i].w=H*D;
}
sort(t+1,t+n+1);
ll m;
scanf("%lld",&m);
for (ll i=1;i<=m;i++)
{
ll H,D;
scanf("%lld%lld",&H,&D);
a[i].w=H*D,a[i].num=i,a[i].ans=1e18;
}
sort(a+1,a+m+1);
for (ll i=1;i<=m;i++)
pp[i]=a[i].w;
for (ll i=1;i<=n;i++)
{
if (t[i].c==t[i-1].c)
continue;
for (ll j=1;j<=C/t[i].c;j++)
{
ll ans=j*t[i].w;
ll l=lower_bound(pp+1,pp+m+1,ans)-pp-1;
a[l].ans=min(a[l].ans,j*t[i].c);
}
}
for (ll i=m-1;i>=1;i--)
a[i].ans=min(a[i].ans,a[i+1].ans);
sort(a+1,a+m+1,cmp);
for (ll i=1;i<=m;i++)
if (a[i].ans<=C)
printf("%lld ",a[i].ans);
else
printf("-1 ");
return 0;
}
E. Star MST(dp恶臭优化+数学)
首先我们可以根据MST的性质发现这样一个性质:
与1相连的任意两边(1,x),(1,y)的边权分别为a,b, 那么(x,y)的边权>=max(a,b),我们可以对与1相连的边权进行排序--()[其中],则>=的边有n-2条,......,>=的边有0条,我们可以用pow解决这组有序的()的方案数。
因此我们可以用dp[i][j]表示i条与1相连的边最大数为j的方案数,则有:
dp[i][j]=
复杂度为O(M+)(其中M为数据预处理)
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 505
#define N 1000005
#define mod 998244353
using namespace std;
ll dp[Ma][Ma];
ll mul[N],pre[N];
ll po(ll p,ll x)
{
ll sum=1;
while (x)
{
if (x&1)
sum=sum*p%mod;
p=p*p%mod;
x>>=1;
}
return sum;
}
void pri()
{
mul[0]=pre[0]=1;
for (ll i=1;i<N;i++)
mul[i]=mul[i-1]*i%mod,pre[i]=po(mul[i],mod-2);
return;
}
int main()
{
pri();
ll n,m;
cin>>n>>m;
n--;
for (ll i=0;i<=m;i++)
dp[i][0]=1;
for (ll i=1;i<=m;i++)
{
for (ll j=1;j<=n;j++)
{
for (ll k=0;k<=j;k++)
dp[i][j]=(dp[i][j]+dp[i-1][k]*pre[j-k]%mod*po(m-i+1,(j-1)*j/2-(k-1)*k/2))%mod;
}
}
printf("%lld\n",dp[m][n]*mul[n]%mod);
return 0;
}