CCF NOI Online 2021 提高组

T1

通过观察奖励箱的位置,发现一个规律:
当这个数对应的二进制数中1的个数为奇数时,它就是奖励箱
于是根据这个规律,通过爆搜查找并存储n以内所有的奖励箱
最后计算结果

code
#include
using namespace std;
const int mod=1e9+7;
int a[100000],k;
long long b[100000],ans=0,d[100000],tot=0;
set<long long> c;
string n;
long long qiuzhi(long long ws)
{
	long long sum=0;
	for(int i=0;i<=ws;i++) if(a[i]==1) sum+=(1<<i);
	return sum;
}
void dfs(bool f,long long ws,string s)
{
	if(ws>n.size()||(ws==n.size()&&s>=n)) return;
	if(f) c.insert(qiuzhi(ws));
	a[ws]=1;
	dfs(!f,ws+1,"1"+s);
	a[ws]=0;
	dfs(f,ws+1,"0"+s);
}
long long power(long long a,long long b) 
{
    long long result=1;
    while(b>0) 
 	{
        if(b&1) result=result*a%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return result%mod;
} 
int main()
{
	cin>>n;
	scanf("%d",&k);
	dfs(0,0,"");
	for(set<long long>::iterator it=c.begin();it!=c.end();it++) d[++tot]=*it;
	for(int i=0;i<k;i++)
	{
		int x;
		cin>>x;
		for(int j=1;j<=tot;j++)
			ans=(ans+(x*power(d[j],i))%mod)%mod;
	}
	printf("%lld",ans);
	return 0;
}

T2

只打了70分的暴力分,三重循环解决此题
枚举b字符串中的连续子串,将这个字串放在a字符串中查找
如果可以查找到
就将这个子串存到set去重
最后输出set的大小即可

code
#include 
using namespace std;
int n,sum=0;
string a,b;
set <string> s;
int main()
{
	bool f;
	cin>>n;
	cin>>a>>b;
	bool f1=0;
	for(int i=1;i<a.size();i++) if(a[i]!=a[i-1]){f1=1;break;}
	if(f1==0)
	{
		cout<<a.size();
		return 0;
	}
	for(int i=0;i<n;i++)
		for(int j=1;i+j<=n;j++)
		{
			int tot=i;
			int k=0;
			string s1="";
			for(int k=i;k<i+j;k++)
				s1+=b[k];
			for(;k<n;k++)
				if(a[k]==b[tot])
				{
					tot++;
					if(tot==i+j)
					{
						s.insert(s1);
						break;
					}
				}
		}
	cout<<s.size();
    return 0;
}

比赛结束前十五分钟想到了一种n^2的算法,但并没有在考试中实现出来,考试完把bug找出来了,但却只有20分,也许哪里错了细节吧
预处理对于每个位置,在它后能找到的每个字母的下标
这样就可以大大减少上面k循环中的查找过程

#include 
using namespace std;
int n,sum=0;
string a,b;
set <string> s;
int c[3030][30],d[30];
int main()
{
	bool f;
	cin>>n>>a>>b;
	for(int i=0;i<n;i++)
		for(int j=i+1;j<n;j++)
			if(!c[i][a[j]-'a']) c[i][a[j]-'a']=j;
	for(int i=0;i<n;i++) if(!d[a[i]-'a']) d[a[i]-'a']=i;
	for(int i=0;i<n;i++)
	{
		string s1="";
		int t;
		if(d[b[i]-'a']) t=d[b[i]-'a'];
		else continue;
		s1+=b[i];
		s.insert(s1);
		for(int j=i+1;j<n;j++)
		{
			if(c[t][b[j]-'a']) t=c[t][b[j]-'a'];
			else break;
			s1+=b[j];
			s.insert(s1);
		}
	}
	cout<<s.size();
	return 0;
}

T3

没有时间思考,就暴力了。。。
思路没的说,照着模拟就行了,应该能拿20分

code
#include
using namespace std;
const int N=1e5+10;
int a[N],b[N],l[N],r[N],c[N],d[N];
int main()
{
	int n,q;
	scanf("%d%d",&n,&q); 
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
	for(int i=1;i<=q;i++) scanf("%d%d%d%d",&l[i],&r[i],&c[i],&d[i]);
	for(int i=1;i<=q;i++)
	{
		int sum=0;
		for(int j=l[i];j<=r[i];j++)
			if((a[j]^c[i])<=min(b[j],d[i])) sum++;
		printf("%d\n",sum);
	}
	return 0;
}

你可能感兴趣的:(c++)