daimayuan week2

T1:加一

题目链接:加一 - 题目 - Daimayuan Online Judge

思路:

用f[i][j]表示数字“i”经过”j“次变换得到的位数,由于每一次都是加一操作可以得到状态转移

  • i:0-8:f[i][j]=f[i+1][j-1]
  • i=9:f[9][j]=f[0][j-1]+f[1][j-1];

经过预处理后,对应查询,依次输出就行了,由于本题数据很大,居然卡输入输出,只能用printf和scanf。

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+5,mod=1e9+7;
int n,f[15][MAX];
int main()
{
	cin>>n;
	for(int i=0;i<=9;i++)f[i][0]=1;//初始化
	for(int i=1;i<=MAX;i++){
		for(int j=1;j<=9;j++){
			f[j][i]=f[j+1][i-1];
		}
		f[9][i]=(f[0][i-1]+f[1][i-1])%mod;//9+1会产生0和1两个数
	}
	for(int i=1;i<=n;i++){
		char c[50];int k;
		int ans=0;
		scanf("%s %d",&c,&k);
		for(int i=0;i<strlen(c);i++){
			ans=(ans+f[c[i]-'0'][k])%mod;
		}
		printf("%d\n",ans);
    }
 	return 0;
}

T2:跳跳

题目链接:跳跳 - 题目 - Daimayuan Online Judge

思路:

如图,我们要求的就是有多少种(A,B)的搭配使得我们可以到达给的任意一个点

 显然对于A的值就是Δx1,Δx2,Δx3的最大公约数,但是这样就很难判断我们是否需要另外一个魔法,不妨将k1先算出来,求出每一组的A,B值去重,这时候伟大的set+pair出现了,set伟大的去重能力,set的大小就是我们需要的魔法数。

#include<bits/stdc++.h>
using namespace std;

int n,ans;
struct dot{
	int x,y;
	
}d[505];
set<pair<int,int> >s;
int main()
{
 	cin>>n;
 	for(int i=1;i<=n;i++)scanf("%d%d",&d[i].x,&d[i].y);
 	for(int p=1;p<=n;p++)
 	{
 		for(int q=1;q<=n;q++){
 			if(p==q)continue;
 			int x=d[q].x-d[p].x,y=d[q].y-d[p].y;
 			int k=__gcd(x,y);
 			int xx=x/k,yy=y/k;//整除会把负号干掉
 			//cout<<k<<"step"<<x<<' '<<y<<"pos"<<xx<<' '<<yy<<endl;
 			if(k<0)s.insert(make_pair(-1*xx,-1*yy));//还原负号
 			else s.insert(make_pair(xx,yy));
		 }	
	}
	cout<<s.size()<<endl;
 	return 0;
}

T3:异或和或

题目链接:异或和或 - 题目 - Daimayuan Online Judge

思路:

  • 异或(1和0)就能产生1,(0和0)只能产生0,(1,1)产生0
  • 或:(1,0)产生1,(1,1)产生1,(0,0)产生0

由上面可以知道1对于这个序列的变化是很重要的,只要这个序列有1就可以产生0,生成任意序列,但是全是0就没办法变化

#include<bits/stdc++.h>
using namespace std;

int n;
string a[1004],b[1005];

bool check(int x){
	int L=a[x].length(),cnt1_a=0,cnt1_b=0;
	for(int i=0;i<L;i++){
		if(a[x][i]=='1')cnt1_a++;
		if(b[x][i]=='1')cnt1_b++;
	}
	if(cnt1_a&&cnt1_b)return 1;
	else return 0;
	
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
	for(int i=1;i<=n;i++){
        if(a[i]==b[i]){//如果相等直接输出YES
			cout<<"YES"<<endl;continue;
		}
		if(a[i].length()!=b[i].length())//如果长度都不相等肯定没办法变
		{
			cout<<"NO"<<endl;continue;
		}
		if(check(i)){//检查是否有1
			cout<<"YES"<<endl;
		}
		else{
			cout<<"NO"<<endl;
		}
	}
 	return 0;
}

T4:01序列

题目链接:01序列 - 题目 - Daimayuan Online Judge

思路:

由数据范围10e6首先就可以排除前缀和+双指针的做法了o(n^2),

  1. 首先特判一下k=0的情况,此时就需要找0子串
  2. 由于01序列的前缀和数组一定是单调递增(非严格),可以用一个cnt【x】这个就是前缀和sum[i]=x出现的次数,只要cnt[x+k]存在(大于0)就可以得到cnt【x】*cnt【x+k】个子串使得1出现的次数是k次

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
long long ans;
void solve(){
    int n, k;
    string str;
    cin >> k >> str;
    n = str.size();
    if (k == 0) {//特判
        std::vector<LL> a;
        LL res = 0;
        for (int i = 0; i < n; i ++) {
            if (str[i] == '0')
                res ++;
            if (str[i] == '1' || i == n - 1) {
                a.push_back(res);
                res = 0;
            }
        }
        LL ans = 0;
        for (auto i : a) 
            ans += (i + 1) * i / 2;//1-i个子串均满足求和
        cout << ans;
        return ;
    }

    LL ans = 0;
    map<LL, LL> mp;
    vector<LL> sum(n + 1);
    mp[0] = 1;
    sum[0] = 0;
    for (int i = 1; i <= n; i ++) {
        sum[i] = sum[i - 1] + str[i - 1] - '0';
        mp[sum[i]] ++;
    }
    int x = 0;
    while (mp[x + k] != 0) {//由于前缀和数组单调递增,只要前面不满足,后面一定不存在
        ans += mp[x] * mp[x + k];
        x ++;
    }
    cout << ans;
}
int main()
{
	solve();
 	return 0;
}

T5:出栈序列判断

题目链接:http://oj.daimayuan.top/course/11/problem/55

模拟模拟

#include <bits/stdc++.h>
using namespace std;
int n,t,s[100010],a[100010];
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    int num = 1;
    for (int i = 1; i <= n; i++)
    {
        while (!t || s[t] != a[i])
        {
            printf("push %d\n", num);
            s[++t] = num;
            num++;
        }
        if (s[t] == a[i])
        {
            printf("pop\n");
            t--;
        }
    }
    return 0;
}

T6:序列维护

题目链接:序列维护 - 题目 - Daimayuan Online Judge

模拟

#include<bits/stdc++.h>
using namespace std;

int n;
vector<int> v;

void Insert(int x,int y){
	v.insert(v.begin()+x,y);
}
int main()
{
	cin>>n;
	string s;int x,y;
	for(int i=1;i<=n;i++){
		cin>>s;
		if(s=="insert"){
			cin>>x>>y;
			v.insert(v.begin()+x,y);
		}
		else if(s=="delete"){
			cin>>x;
			v.erase(v.begin()+x-1);
		}
		else if(s=="query"){
			cin>>x;
			cout<<*(v.begin()+x-1)<<endl;;
		}
	}


 	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值