2021年广东工业大学第11届腾讯杯新生程序设计竞赛

B 过生日

    Alice在黑板上快速的写出了一个字符串和一个数字k,Alice想让Bob找到是否有这样一个区间,使得其中的一个字符的个数大于等于k。告诉Alice是否可以找到符合条件区间。如果可以找到请告诉Alice最短的区间长度。
input:

4
aba
2
abc
2
abczgbnhe
2
abczgbnaegsca
3

output:

3
-1
5
13

 法1、尺取法(更新区间,维护)尺取法

#include
using namespace std;
int main() {
	int t; cin >> t;
	while (t--) {
		string s; cin >> s;
		int k; cin >> k;
		int ans = 1e9;
		int cnt[26]{};
		for (int i = 0,j=0; i < s.length()&&j

 法2、二分答案

前缀和 + 二分答案 二分答案

#include
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 2e5 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
ll sum[maxn][30];
bool check(int x){
	for(int i = x; i <= n; ++i){
		for(int j = 0; j < 26; ++j)
			if(sum[i][j] - sum[i-x][j] >= m) return 1;
	}
	return 0;
}
void work()
{
	string s;
	cin >> s >> m;
	n = s.size();
	s = "@" + s;
	for(int i = 1; i <= n; ++i){
		for(int j = 0; j < 26; ++j)
			sum[i][j] = sum[i-1][j];
		sum[i][s[i]-'a']++;
	}
	int l = 0, r = n;
	while(l < r){
		int mid = (l + r) >> 1;
		if(check(mid)) r = mid;
		else l = mid  + 1;
	}
	if(l == n && !check(l)) cout << -1 << endl;
	else cout << l << endl;
}

int main()
{
	ios::sync_with_stdio(0);
	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

小代写法: 

#include 
using namespace std;
vector a[128];
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	int t;
	cin>>t;
	while (t--)
	{
		string s;
		int n,i,j,k,ans=1<<20;
		cin>>s>>k;
		for (i=0;i<128;i++) a[i].clear();
		for (i=0;i=k)
		{
			for (j=k-1;j


F

求osu的子序列数量

思维: 站在s的角度想 站在u 的角度想;有点像 足球比分的题目 站在记录的前一项的角度想后一项

1、好解
int n;
char a[N];
void solve(){
    cin>>n;
    scanf("%s",a+1);
    int x=0,y=0,z=0;
    for(int i=1;i<=n;i++){
        if(a[i]=='o')x++;
        else if(a[i]=='s')y+=x;
        else if(a[i]=='u')z+=y;
    }
    cout<

C  Java

并且要删除重复的资源(删获取时间早的)

<删除这个动作怎么完成?

1、覆盖第一次出现的值

sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)mp[a[i].x]=a[i].t;
    for(int i=1;i<=n;i++){
        if(a[i].t==mp[a[i].x])ans[++cnt]=a[i].id;
    }
 map>s;
    for (int i = 0; i < v.size(); i++) {
        s[v[i].name] =make_pair(v[i].t,v[i].id);
    }

2、用bool   (map可以覆盖所有bool情况,int类型又可以覆盖bool情况(可以直接让 mp[i]++ 在需要判断的时候先  mp[i]--;  if(mp[i])continue;  ))

为什么我的程序有bug? 因为动了i和n两个变量而且还有一个下标不能随着i变他只能++

思路混乱的原版:
for(int i =1;i<=n;i++){
		cin>>s;
		cin>>t;
		if(find(s)){
			if(t>ar[find(s)].t){ar[find(s)].t = t;ar[find(s)].i = i+z;}
			n--;
			i--;
			z++;
		}
		else{ar[i].i=i+z;ar[i].s=s;ar[i].t=t;}
	}

改正:
int tmp = 1;
for(int i =1;i<=n;tmp++){
		cin>>s;
		cin>>t;
		if(find(s)){
			if(t>ar[find(s)].t){ar[find(s)].t = t;ar[find(s)].i =tmp;}
			n--;
		}
		else{ar[i].i=tmp;ar[i].s=s;ar[i].t=t;i++;}
	}

 小代写法:


int main(){
	int n;
	cin >> n;
	std::vector> a;
	std::map mp;
	rep(i,1,n + 1){
		string s;int x;
		cin >> s >> x;
		mp[s]++;
		a.pb({x,s,i});
	}
	sort(all(a));
	for(auto[x,y,z]:a){
		--mp[y];
		if(mp[y])continue;
		cout<

Problem G 拼牛牛

  • 函数收敛性相关 可以明显看出增长数字是一个等比数列,根据等比数列的求和公式知道 ((1 - k^n)/(1 - k ) 在k小于1大于0时,函数收敛,极限值是1/(1−k)因此只要比较这个极限是否小于等于当前还差的钱数,如果小于等于还差的钱数则一定不能够提现,否则一定可以提现。
  • 打表思想:直接0.1~0.9试一下 感觉一下
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;double k;
        cin>>n>>k;
        n=100-n;
        if(1.0/(1-k)>n+1e-10)cout<<"YES\n";
        else cout<<"NO\n";
    }
}

Problem D 机器人

按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。按题意模拟。

int n,k;
int a[N][N];
bool check(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
                 
            if((i-1)*n+j!=a[i][j])return 0;
        }
    }
    return 1;
}
void f(){
    int t=a[1][1];
    for(int i=2;i<=n;i++)a[1][i-1]=a[1][i];
    for(int i=2;i<=n;i++)a[i-1][n]=a[i][n];
    for(int i=n-1;i>=1;i--)a[n][i+1]=a[n][i];
    for(int i=n-1;i>=1;i--)a[i+1][1]=a[i][1];
    a[2][1]=t;
}
void solve(){
    scanf("%d",&n);
    int flag=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i=1;i<=100;i++){
        f();
        if(check()){
            cout<<"YES";return;
        }
 
    }
    cout<<"NO";
}



假设灯的初始状态是暗的,我每拉动一次开关,灯就会有ppp的概率转换状态(亮->暗 或 暗->亮)。那么当我拉动nnn次之后,灯是亮着的概率是多少呢?

把他抽象成每一个状态 发现下一个状态和上一个是有关系的 无论你使用递归完成这个状态的转移 还是用pre记录一下 还是用dp 前提是你知道两个状态是类似于递推关系没有上一个就不会有下一个 得到下一个的前提是有上一个

别局限于用数学公式解决 用编程的思维 自顶向下

dp状态转移:
dp[105][2]
dp[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            dp[i][0]=1.0*dp[i-1][1]*p+(1.0*dp[i-1][0]*(1-p));
            dp[i][1]=1.0*dp[i-1][0]*p+(1.0*dp[i-1][1]*(1-p));
        }

 x = 0, y = 1;
        for(int i = 1; i <= n; i++)
        {
            a = x * (1 - p) + y * p, b = x * p + y * (1 - p);
            x = a, y = b;
        }

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