牛客小白月赛31

A|B

题目描述

给定两个正整数a,x,统计满足以下条件的b的个数:

1≤b≤x
a|b=a+b
输入描述:
第一行给出一个 t, 1\le t \le 10^5t,1≤t≤10
5

接下来 t 行每行一对正整数 a,x,1\le a,x \le 10^9a,x,1≤a,x≤10
9

输出描述:
输出 t 行,每行一个正整数
输入
2
1 2
2 3
输出
1
1

主要思路:
如果a:110110,则b:0000
即a中二进制存在1的位置在b中一定是0
而且b有x的范围限制

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int s[101]={0};
	for(int i=0;i<31;i++)
		s[i]=pow(2,i);
	int t;
	cin>>t;
	while(t--)
	{
		int a,x,bit,ans=0,bit2,c;
		cin>>a>>x;
		for (bit = (1 << 30); bit; bit >>= 1)//找到x的二进制位数
		{
			if((bit&x)==0)	continue;
			c=0;
			for(int bit2=(bit>>1);bit2;bit2>>=1)//当第i位为0时,后面的情况
			{
				if((bit2&a)==0) c++;
			}
			ans+=s[c];
            if (bit & a) break;//如果第i位不能为1,则不用继续讨论
            //继续循环判断第i位为1时的情况
		}
		if((a|x)==(a+x)) ans++;
		cout<<ans-1<<endl;//减去0这种情况
	}
	return 0;	
} 

A+B(待补)

作者:Dong_pope
链接:https://ac.nowcoder.com/discuss/587485?type=101&order=0&pos=2&page=1&channel=-1&source_id=1
来源:牛客网

#include <iostream>
#include <map>
 
using namespace std;
 
int n;
string a[5];
map<string, int> mp;
string num[11] = {"####.##.##.####",
                  "..#..#..#..#..#",
                  "###..#####..###",
                  "###..####..####",
                  "#.##.####..#..#",
                  "####..###..####",
                  "####..####.####",
                  "####.##.#..#..#",
                  "####.#####.####",
                  "####.####..####",
                  "....#.###.#...."};
 
signed main() {
//    freopen("in", "r", stdin), freopen("out", "w", stdout);
    mp["####.##.##.####"] = 0;
    mp["..#..#..#..#..#"] = 1;
    mp["###..#####..###"] = 2;
    mp["###..####..####"] = 3;
    mp["#.##.####..#..#"] = 4;
    mp["####..###..####"] = 5;
    mp["####..####.####"] = 6;
    mp["####.##.#..#..#"] = 7;
    mp["####.#####.####"] = 8;
    mp["####.####..####"] = 9;
    mp["....#.###.#...."] = 10;
    int Test;
    cin >> Test;
    for (int Case = 1; Case <= Test; Case++) {
        string s;
        getline(cin, s);
        for (auto &i : a) {
            getline(cin, i);//string安全输入函数
            n = i.size();
        }
        int ans = 0;
        int sum = 0;
        for (int j = 0; j < n; j += 4) {
            string sub = "";
            for (int i = 0; i < 5; i++)sub += a[i].substr(j, 3);//截取字符串函数
            int tmp = mp[sub];
            if (tmp == 10)ans += sum, sum = 0;
            else sum = sum * 10 + tmp;
        }
        ans += sum;
        string res[5] = {"", "", "", "", ""};
        if (ans == 0) {
            for (int i = 0, j = 0; i < 5; i++, j += 3) {
                res[i] = num[0].substr(j, 3) + res[i];
            }
        } else {
            while (ans) {
                for (int i = 0, j = 0; i < 5; i++, j += 3) {
                    res[i] = num[ans % 10].substr(j, 3) + res[i];
                }
                ans /= 10;
                if (ans) {
                    for (int i = 0; i < 5; i++)res[i] = "." + res[i];
                }
            }
        }
        for (int i = 0; i < 5; i++)cout << res[i] << endl;
        if (Case < Test)cout << endl;
    }
    return 0;
}

图像存储

链接:https://ac.nowcoder.com/acm/contest/12529/C
来源:牛客网

题目描述
数字图像是一个由“0”和“1”这两个元素组成的矩阵,除去边角上的元素,每个元素都有上下左右相邻的四个元素。再一个数字图像中,元素“0”代表空白,只有元素“1”所在的位置才有一个黑点。由此,一副黑白的图像得以显现。

为了能在更少的空间里存储更多的图像,一个可行的办法就是每种相同的黑块只保留一个,其他的地方只保留位置,这样便实现了压缩。查看时,只需将保留的黑块拓印到其它的位置,这样就实现了图像的复原。

可见,该技术的关键就是对不同的黑块进行记录。我们把由若干个相邻的“1”构成的区域定义为黑块,规定一个孤立的“1”也是一个黑块,黑块中“1”的个数为黑块的大小,通过上下左右平移可以实现重合并且等大的黑块为同一种黑块。现在你的任务是分别算出一个图像中黑块的个数和种数。
输入描述:
多组输入,最多不超过1000组

首行输入2个整数 n , m(1<= n , m <=10^3 )代表图像的尺寸。

接下来输入一个n行m列的01矩阵(0和1之间无空格间隔)

以一行中两个0结束输入

n*m的和小于1e7

输出描述:
对于每组输入在一行中输出给定图像中黑块的个数和不同的黑块的种数。
示例1
输入
6 6
001100
001001
000011
101000
000110
000100
5 6
111101
100100
100101
100100
111101
0 0
输出
5 3
4 2

主要思路:
这是一个简单的搜索,主要难点是利用哈希表来存储1的形状

#include<iostream>
#include<map>
using namespace std;
int ans,g,n,m,aa,bb,dis[][2]={1,0,-1,0,0,1,0,-1};
long long f;
map<long long,int> u;
char a[1001][1001];
void dfs(int x,int y)
{
    a[x][y]='0';
    f=(f*1005005+(x-aa+n)*1005+y-bb+m)%2070000001;
    for(int i=0;i<4;i++)
       if(a[x+dis[i][0]][y+dis[i][1]]=='1'&&x+dis[i][0]>=0&&x+dis[i][0]<n&&y+dis[i][1]>=0&&y+dis[i][1]<m)
           dfs(x+dis[i][0],y+dis[i][1]);
}
int main()
{
    while(cin>>n>>m&&n&&m)
    {
        ans=g=0;
        u.clear();//记得清空
        for(int i=0;i<n;i++)
            cin>>a[i];
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(a[i][j]=='1')
                {
                    ans++;
                    f=0;//记得每次搜索前初始化f
                    dfs(aa=i,bb=j);
                    if(!u[f])
                        g++,u[f]++;
                }
            }
        cout<<ans<<' '<<g<<endl;
    }
    return 0;
}

解方程

链接:https://ac.nowcoder.com/acm/contest/12529/E
来源:牛客网

题目描述
给出两个正整数 a,b,计算满足方程 ax+by=x*y 的正整数(x, y) 的组数。
输入描述:
输入的第一行有一个正整数 t 测试数据的组数。

每组测试数据在一行中给出两个正整数 a,b。

输出描述:
输出一个数字表示答案

保证答案小于2^{31}2
31

示例1
输入
2
1 2
2 3
输出
2
4

主要思路:
由ax+by=xy;
a
b+xy=ax+by+ab
ab=ax+by+ab-xy
a
b=(a-y)(b+x)
ab=xxyy
即xx与yy均为a*b的约数

#include<iostream>
#include<algorithm>
using namespace std;
int prim[1000001];
bool book[1000001];
void primm(int n)//素数筛
{
    int cnt=0;
    for( int i=2;i<=n;i++)
    {
        if(!book[i])
           prim[cnt++]=i;
        for(int j=0;j<cnt&&prim[j]*i<n;j++)
        {
            book[prim[j]*i]=1;
            if(i%prim[j]==0)
                break;
        }
    }
}
int main()
{
    primm(1000001);
    int t;
    cin>>t;
    while(t--)
    {
        long long a,b,num;
        cin>>a>>b;
        num=a*b;
        int ans=1;
        if(num==1)
        {
            cout<<ans<<endl;
        }
        else
        {
            int k=0;
            while(num>1)//约数个数定理
            {
                if(num%prim[k]==0)
                {
                    int n=0;
                    while(num%prim[k]==0)
                    {
                        n++;//取指数
                        num/=prim[k];
                    }
                    ans*=(n+1);
                }
                k++;
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

消减整数

题目描述
链接:https://ac.nowcoder.com/acm/contest/12529/F
来源:牛客网

给你一个数字N依序减掉1,2,3,…直到不够减。如果刚好减到0就结束,否则就加上N继续从1开始减,直到减到0为止。

请给出一个数字,计算对于该数字一共重复了几次这个过程。

输入的第一行有一个正整数 t, 1 \le t \le 10^4t,1≤t≤10 ^4
,代表测试数据的组数

接下来t行每行一个数 N, 1 \le N \le 10^8N,1≤N≤10 ^8

输出描述:
对于每组输入,若能够在有限次内削减为0,在一行中输出重复的过程次数,否则输出 “Impossible”。
示例1
输入
3
1
2
3
输出
1
2
1
主要思路:
第一次剩下m,第二次剩下2m直至nm>=k;
所以求m和k的最小公倍数

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        int x=1;
        while((n-x)>0)
        {
            n-=x;
            x++;
        }
        if(n-x==0)
        	cout<<'1'<<endl;
        else
        {
            for(int i=2;;i++)
            {
                if(i*n%x==0)
                {
                    cout<<i<<endl;
                    break;
                }
            }
	    }
    }
}

简单题的逆袭

给定x,y,找出满足方程 x^k≤y 的最大的k
输入t
x,y

#include<iostream>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        long long x,y;
        cin>>x>>y;
        if(x<=1||y==0) cout<<"-1"<<endl;
        else
        {
            int ans=0;
            while(y>=x)
            {
                ans++;
                y/=x;
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

对称之美

链接:https://ac.nowcoder.com/acm/contest/12529/H
来源:牛客网

题目描述
给出n个字符串,从第1个字符串一直到第n个字符串每个串取一个字母来构成一个新字符串,新字符串的第i个字母只能从第i行的字符串中选出,这样就得到了一个新的长度为n的字符串,请问这个字符串是否有可能为回文字符串?
输入描述:
第一行一个数字 t ,1\le t \le50t,1≤t≤50,代表测试数据的组数

每组测试数据先给出一个数字 n,然后接下来n行每行一个只由小写字母组成的字符串
输出描述:
在一行中输出 “Yes” or “No”
示例1
输入
2
1
a
3
a
b
c
输出
Yes
No
主要思路:
从外到内一层一层地判断

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,flag=0;
		string a[100001];
		cin>>n;
		for(int i=1;i<=n;i++)
			cin>>a[i];
		for(int i=1,j=n;i<=j;i++,j--)
		{
			flag=0;
			for(int k=0;k<a[i].size();k++)
				for(int l=0;l<a[j].size();l++)
				{
					if(a[i][k]==a[j][l])
					{
						flag=1;
						break;
					}
				}
			if(!flag)
				break;	
		}
		if(flag)
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;
	}
	return 0;
}

非对称之美

题目描述
给出一个字符串,求最长非回文子字符串的长度
示例1
输入
meow
输出
4
主要思路:
①本身就不严格对称,输出n
②相邻不完全对称,输出n-1
③完全对称,如aaaaa,输出0

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    string a;
    cin>>a;
    int ans=0,flag=0;//③
    for(int i=0,j=a.size()-1;i<=j;i++,j--)
    {
        if(a[i+1]!=a[j]||a[i]!=a[j-1])//②
        {
            flag=1;
        }
        if(a[i]!=a[j])//①
        {
            ans=a.size();
            break;
        }
    }
    if(flag)
    {
        int n=a.size()-1;
        ans=max(ans,n);
    }
    cout<<ans<<endl;
    return 0;
}

排列算式

链接:https://ac.nowcoder.com/acm/contest/12529/J
来源:牛客网

题目描述
给出n数字,对于这些数字是否存在一种计算顺序,使得计算过程中数字不会超过3也不会小于0?

输入
2
4
+3 +2 -1 -2
5
+3 +2 +1 +0 +2
输出
Yes
No
说明
第一组依照 +3,−2,+2,−1 的顺序由左至右计算总和,过程会依序算得 3, 1, 3, 2,满足题目要求

很显然第二组不存在满足要求的计算顺序

主要思路:
主要运用贪心的方法,排除不正确的情况
如果sum<0||sum>3||判断
仅仅判断-3、+3能否抵消即可
因为sum有限制

#include<iostream>
#include<cstring>
using namespace std;
int a[1001];
int judje()
{
	while(a[0])
	{
		if(a[6]) a[6]--;//3
		else if(a[5]>1&&a[2]) a[5]-=2,a[2]--;//2+2-1
		else if(a[5]&&a[4]) a[5]--,a[4]--;//2+1
		else if(a[4]>2) a[4]-=3;//1+1+1
		else return 0;
		a[0]--;
	}
	while(a[6]>1)
	{
		if(a[1]>1&&a[4]) a[1]-=2,a[4]--;//-2-2+1
		else if(a[1]&&a[2]) a[1]--,a[2]--;//-2-1
		else if(a[2]>2) a[2]-=3;//-1-1-1
		else return 0;
		a[6]--;
	}
	return 1;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(a,0,sizeof(a));
		int n,sum=0,x;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			cin>>x;
			sum+=x;
			a[x+3]++;
		}
		if(sum<0||sum>3||!judje())	cout<<"No"<<endl;
		else
			cout<<"Yes"<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值