A. Password(傻逼题)
刚开始看了半年没看懂,后来发现不管前导0的,答案即为6*C(10-n,2)
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
void sol()
{
scanf("%lld",&n);
for (ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
printf("%lld\n",6*(10-n)*(10-n-1)/2);
return;
}
int main()
{
ll tt;
scanf("%lld",&tt);
while (tt--)
sol();
return 0;
}
B. Permutation Value(思维)
只需构造1,n开头便可以搞出唯一答案
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
void sol()
{
scanf("%lld",&n);
printf("1 %lld\n",n);
for (ll i=2;i<n;i++)
printf("%lld ",i);
printf("\n");
return;
}
int main()
{
ll tt;
scanf("%lld",&tt);
while (tt--)
sol();
return 0;
}
C. Save the Magazines(贪心/dp)
我们发现对于一个完整的连续1段,假设连续1段为[l,r],则这个完整的连续1段的最大贡献为
并且有每段贡献独立,答案即为最大贡献和
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
string s;
void sol()
{
scanf("%lld",&n);
cin>>s;
for (ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
ll ans=0,mi=a[n];
for (ll i=n;i>=1;i--)
{
ans+=a[i];
if (s[i-1]=='1')
mi=min(mi,a[i]);
else
ans-=min(mi,a[i]),mi=a[i-1];
}
printf("%lld\n",ans);
return;
}
int main()
{
ll tt;
scanf("%lld",&tt);
while (tt--)
sol();
return 0;
}
D. Problem with Random Tests(暴力+思维)
首先我们思考一个串
0000111110111000
1.对于该串的前导0部分,我们无法修改,因此该串可以简化为:
111110111000
2.对于更新后的该串前导1部分已经很完美了,我们也不需要进行修改
3.由于串为二进制形式,对于前导1后面的那个0,我们可以把它修改为1,而想要将其修改为1只能用前导1部分
如:s=111110111000,
t= 11111011100;
但对于后面的1我们无法修改到那个0上(因为小位不能修改大位)
因此就可以理解题目中的随机化拉!
假设出现<=100个前导0后的前缀1,那么复杂度即为O(100n),而错误几率为。
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
string s,t;
void sol()
{
scanf("%lld",&n);
cin>>s;
string ma=s;
ll l=-1;
for (ll i=0;i<n;i++)
{
if (s[i]=='0')
l++;
else
break;
}
l++;
if (l==n)
{
printf("0\n");
return;
}
ll f=l;
for (ll i=l;i<n;i++)
{
if (s[i]=='1')
f=i;
else
break;
}
f++;
for (ll i=l;i<f;i++)
{
string ans=s;
ll p=i;
for (ll j=f;j<n;j++)
{
ans[j]=(s[p]-'0')|(ans[j]-'0')+'0';
p++;
}
for (ll j=l;j<n;j++)
{
if (ans[j]<ma[j])
break;
else if (ans[j]>ma[j])
{
ma=ans;
break;
}
}
}
for (ll i=l;i<n;i++)
printf("%c",ma[i]);
return;
}
int main()
{
sol();
return 0;
}
E. FTL(dp)
首先我们规定状态为(w1,w2,g,ti),其中w1为1号充能时间,w2为2号充能时间,g为已经造成的有效伤害,ti为花费的总时间,我们很容易发现其状态有以下三种形式:
(我们默认p1<p2)
(0,0,g,ti),(0,a,g,ti),(b,0,g,ti)
对于所有状态我们会有两种递推情况:
1.->(a,b,g+pi-s,t+T) (a||b)
2.->(0,0,g+p1+p2-s,t+T)
我们可以发现g与ti保证递增有序,那么我们可以将(0,0,g,ti)设置为初始状态,由于相比于ti,g更好成为固定点(因为g<=5000,ti<=5000*1e12)
因此我们枚举g递增,通过1更新答案,2更新初始状态。
复杂度O()
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 5005
#define mod 1000000007
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll a[Ma];
ll ask[Ma];
ll p1,t1,p2,t2,h,s;
void sol()
{
cin>>p1>>t1>>p2>>t2>>h>>s;
memset(ask,0x3f,sizeof(ask));
ask[0]=0;
ll ans=1e18;
for (ll ca=0;ca<=h;ca++)
{
ll w1=0,w2=0,ti=ask[ca],g=ca;
while (g<h)
{
ll w=max(t1-w1,t2-w2);
if (g+p1+p2-s>=h)
ans=min(ans,ti+w);
else
ask[g+p1+p2-s]=min(ask[g+p1+p2-s],ti+w);
w=min(t1-w1,t2-w2);
ti+=w,w1+=w,w2+=w;
if (w1==t1)
w1=0,g+=p1-s;
if (w2==t2)
w2=0,g+=p2-s;
if (g>=h)
ans=min(ans,ti);
}
}
printf("%lld\n",ans);
return;
}
int main()
{
sol();
return 0;
}
F. Intersection and Union(思维+数据结构)
我们假设前i-1个op操作后,对于集合有数字p出现的贡献为pre1,集合没有有数字p出现的贡献为pre0。我们很容易发现pre0+pre1=
那么对于第i个op操作
如果中有数字p,那么pre1将更新为(pre0+pre1)*2[pre0可以用∪,⊕;pre1可以用∩,∪]
如果中没有数字p,那么pre1将更新为(pre1)*2[pre0无法保留;pre1可以用∩,⊕]
那么对于一个数字p,
我们发现只有最后一次在集合S中出现的数字p才是有效的,那么我们就可以用segtree维护区间最大,再单点询问即可。
PS:注意的情况。
复杂度:
#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 998244353
#define N 300005
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
ll n;
ll a[Ma];
ll po3[Ma],po2[Ma];
struct node
{
ll l,r,ma,add;
}t[Ma<<2];
void build(ll p,ll l,ll r)
{
t[p].l=l,t[p].r=r,t[p].ma=t[p].add=0;
if (l==r)
return;
ll mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
t[p].ma=max(t[ls].ma,t[rs].ma);
return ;
}
void spread(int p){
if(t[p].add){
t[ls].ma=max(t[ls].ma,t[p].add);
t[rs].ma=max(t[rs].ma,t[p].add);
t[ls].add=max(t[ls].add,t[p].add);
t[rs].add=max(t[rs].add,t[p].add);
t[p].add=0;
}
return ;
}
void change(ll p,ll l,ll r,ll d)
{
if(l<=t[p].l&&r>=t[p].r)
{
t[p].ma=max(t[p].ma,d);
t[p].add=max(t[p].add,d);
return;
}
spread(p);
ll mid=(t[p].l+t[p].r)>>1;
if(l<=mid)change(ls,l,r,d);
if(r>mid)change(rs,l,r,d);
t[p].ma=max(t[ls].ma,t[rs].ma);
return ;
}
ll ask(ll p,ll l,ll r)
{
if(l<=t[p].l&&r>=t[p].r)return t[p].ma;
spread(p);
ll mid=(t[p].l+t[p].r)>>1;
ll val=0;
if(l<=mid)val=max(val,ask(ls,l,r));
if(r>mid)val=max(val,ask(rs,l,r));
return val;
}
void sol()
{
scanf("%lld",&n);
po2[0]=po3[0]=1;
for (ll i=1;i<=N;i++)
po3[i]=po3[i-1]*3%mod,po2[i]=po2[i-1]*2%mod;
build(1,0,N);
for (ll i=1;i<=n;i++)
{
ll l,r;
scanf("%lld%lld",&l,&r);
change(1,l,r,i);
}
ll ans=0;
for (ll i=0;i<=N;i++)
{
ll w=ask(1,i,i);
if (!w)
continue;
else if (w==1)
ans=(ans+po2[n-1])%mod;
else
ans=(ans+po2[n-w+1]*po3[w-2]%mod)%mod;
}
printf("%lld\n",ans);
return;
}
int main()
{
sol();
return 0;
}