今天真的是太废啦!!!!!!
Lusir的游戏
当前能量为e,如果e<h[i+1],那么e-(h[i+1]-e)=2e-h[i+1],否则e+e-h[i+1]=2e-h[i+1];所以无论是大于还是小于变化都是一样的,就按样例来说到最后的能量为32e-16h[1]-8h[2]-4h[3]-2h[4]-h[5],显然是和2的n次方有关系,但是由于数太大,我们把乘以2的n-i-1次方改为除以2的i次方,最后加起来向上取整就可以了;
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1000000007;
const ll inf=0x3f3f3f3f;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll n;
double h[100005];
int main(){
//freopen("in.txt","r",stdin);
scanf("%lld",&n);
double y=2,sum=0;
for(int i=1;i<=n;i++){
scanf("%lf",&h[i]),h[i]/=y;
y*=2;
sum+=h[i];
}
ll ans=ceil(sum);
printf("%lld\n",ans);
return 0;
}
Get an Even String
最少删掉几个数也就是最大能保留多少数,用dp[i]代表前i个字符能保留多少个字符,dp[i]=max(dp[i],dp[last[s[i]]-1]+2);因为不能和上一对重复,所以last[s[i]]要减1;当时就是不知道如何来找这个字母的上一个位置,真是蠢到家了,用一个map就可以了呀,哎,,,
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1000000007;
const ll inf=0x3f3f3f3f;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll t,n,dp[200005];
map<char,int>mp;
string s;
int main(){
// freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
cin>>s;n=s.size();
s="0"+s;
for(int i=0;i<=n;i++) dp[i]=0;
mp.clear();
for(int i=1;i<=n;i++){
dp[i]=dp[i-1];
if(mp[s[i]])
dp[i]=max(dp[i],dp[mp[s[i]]-1]+2);
mp[s[i]]=i;
}
printf("%lld\n",n-dp[n]);
}
return 0;
}
Maximum Product Strikes Back
让c题搞得这题也没心态想了,越想情况越复杂,最后直接崩了,,,只有当多个2相乘才可以改变最大值为1的情况,统计一下前i个数字出现i的次数,然后再用一个数组记录一下记录每一段离i最远且使乘积不为负的位置(这个地方好难想,不会实现)
Codeforces Round #780 (Div. 3) - 知乎 (zhihu.com)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1000000007;
const ll inf=0x3f3f3f3f;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll t,n,a[200005],val[2]={0,-1},two[200005];
int main(){
// freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
ll l=0,r=n,cnt=0,maxx=0;
val[0]=0,val[1]=-1;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
two[i]=two[i-1];
if(abs(a[i])==2) two[i]++;
if(a[i]<0) cnt++;
if(val[cnt%2]>=0){
if(maxx<two[i]-two[val[cnt%2]]){
maxx=two[i]-two[val[cnt%2]];
l=val[cnt%2],r=n-i;
}
}
if(a[i]==0){
cnt=0;
val[0]=-1;
val[1]=-1;
}
if(val[cnt%2]==-1) val[cnt]=i;//记录每一段离i最远且使乘积不为负的位置
}
printf("%lld %lld\n",l,r);
}
return 0;
}
Matrix and Shifts
只要看看对角线最多能有多少个1就可以,假设对角线最多有ans个1,整个矩阵有sum个1,那么答案就是对角线上0的个数加上除对角线外矩阵有1的个数,也就是sum+n-2*ans;
Codeforces Round #780 (Div. 3) C D E F - 知乎 (zhihu.com)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1000000007;
const ll inf=0x3f3f3f3f;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll t,n,a[2005][2005];
char ch[2005][2005];
int main(){
// freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
ll ans=0,sum=0,maxx=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) a[i][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>ch[i][j];
if(ch[i][j]=='1') a[i][j]=1,sum+=1;
}
for(int i=1;i<=n;i++){
maxx=0;
for(int j=0;j<n;j++){
ll x=(i+j)%n==0?n:(i+j)%n;
if(a[j+1][x]==1) maxx++;
}
ans=max(maxx,ans);
}
printf("%lld\n",sum+n-2*ans);
}
return 0;
}
Promising String (hard version) 树状数组优化
观察一个字串可以得出一个结论,假设字串中加号的个数为ja,减号的个数为sub,减号能转化成加号的个数为add,则sub-2*add==add+ja;转化一下也就是要满足(sub-ja)%3==0&&(sub-ja)/3<=add;也就是说减号一定会大于等于加号,那我们设加号为-1,减号为1,那字串要满足的条件就是
sum[i]-sum[j]>=0,(sum[i]-sum[j])%3==0,也就是sum[i]>=sum[j];那把sum存入树状数组里,每次查i的时候只要看看有多少小于他的数就可以了,但是要设三个树状数组,因为mod3会有三种情况0,1,2只有当sum[i],sum[j]同余的时候才可以满足(sum[i]-sum[j])%3==0;另外树状数组不会有负数,找个加上最小负数的相反数加一就可以了,一开始入树状数组的时候一定要把0(或者是最小负数的相反数加一,也就是sum[0])先入进去,因为前缀和也是要考虑sum[0]的呀,比如求从1到i的子串,就需要sum[i]-sum[0];
Codeforces Round #780 (Div. 3) C D E F - 知乎 (zhihu.com)
#include <bits/stdc++.h>
#define ll long long
#define lowbit(i) ((i)&(-i))
using namespace std;
const ll mod=1000000007;
const ll inf=0x3f3f3f3f;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
ll t,n,sum[500005],a[300005];
string s;
struct shu{
ll tr[500005];
void add(ll x,ll y){
for(int i=x;i<=500005;i+=lowbit(i))
tr[i]+=y;
}
ll ask(ll x){
ll res=0;
for(int i=x;i;i-=lowbit(i))
res+=tr[i];
return res;
}
void init(ll ca){
for(int i=1;i<=ca;i++) tr[i]=0;
}
}tree[3];
int main(){
//freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
cin>>s;
s="0"+s;
ll mi=0;
for(int i=0;i<=n;i++) sum[i]=0;
for(int i=1;i<=n;i++){
if(s[i]=='+') sum[i]=sum[i-1]-1;
else sum[i]=sum[i-1]+1;
mi=min(mi,sum[i]);
}
mi=-mi+1;
for(int i=0;i<=n;i++) sum[i]+=mi;
for(int i=0;i<3;i++) tree[i].init(n+mi);
ll ans=0;
for(int i=0;i<=n;i++){//不加0的话就会漏掉从1开始的字符串的情况
ll m=sum[i]%3;
ans+=tree[m].ask(sum[i]);
tree[m].add(sum[i],1);
}
printf("%lld\n",ans);
}
return 0;
}