2021-08-04

题目
比赛的时候读懂了题目,但是不会,硬写会T。果然赛后自己写的就T了,还用了树状数组和快速幂,十分暴力。然后看了大佬的代码,觉得精妙无比。原理是这样,条件是按照输入的顺序,必须有一个1,至少有1个2,必须有1个3。对于每一个1,它后面的2都有选与不选两种可能,且相互独立。但是我们还需要记录1的个数,或者说是都不选的情况的个数。所以对于每一个3,就用当前的情况数减去1的个数。

#include <bits/stdc++.h>
using namespace std;
#define T int T; scanf("%d", &T); while(T--)
#define lowbit(i) ((i)&(-i))
typedef long long ll;
const int mod=1e9+7;

int main()
{
    int n, a, cnt=0, res=0, ans=0;
    scanf("%d", &n);
    for(int i=1; i<=n; i++){
    	scanf("%d", &a);
    	if(a==1){
    		res+=1;
    		res%=mod;
    		cnt+=1;
    	} else if(a==2){
    		res*=2;
    		res%=mod;
    	} else if(a==3){
    		ans+=res-cnt;
    		ans%=mod;
    	}
    }

    printf("%d\n", ans);
	return 0;
}

顺便复习一下快速幂的写法

ll binaryPow(ll a, ll b){
	ll ans=1;
	while(b){
		if(b&1)
			ans=ans*a%mod;

		a=a*a%mod;
		b>>=1;
	}

	return ans;
}

这里贴一份第二次补题时写的代码,这份代码会T。但是通过这道题,发现1和3之间的2的个数为 n n n。这样的组合有 2 n − 1 2^{n}-1 2n1种,而且上一份代码将1d的个数转化为这个-1的数量。而对于1和3就是单纯地累积,也就是影响 2 n − 1 2^{n-1} 2n1前面的系数。

#include <bits/stdc++.h>
using namespace std;
#define T int T; scanf("%d", &T); while(T--)
typedef long long ll;
const ll mod=1e9+7;
const int N=1e6+10;
ll sum=0,  b1[N];

int main()
{
	memset(b1, 0, sizeof b1);
	int n, b, cnt=0;
    scanf("%d", &n);

    for(int i=0; i<n; i++){
    	scanf("%d", &b);
    	if(b==1){
    		b1[cnt++]=1;
    	} else if(b==2){
    		for(int j=0; j<cnt; j++){
    			b1[j]<<=1;
    			b1[j]%=mod;
    		}
    	} else {
    		for(int j=0; j<cnt; j++){
    			sum+=(b1[j]-1);
    			sum%=mod;
    		}
    	}
    }

    printf("%lld\n", sum);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值