代码源dev2刷题

有一个n×nn×n的网格,有些格子是可以通行的,有些格子是障碍。

一开始你在左上角的位置,你可以每一步往下或者往右走,问有多少种走到右下角的方案。

由于答案很大,输出对109+7109+7取模的结果。

输入格式
第一行一个正整数nn。

接下来nn行,每行nn个正整数,11表示可以通行,00表示不能通行。

输出格式
一个整数,表示答案。

样例输入
3
1 1 1
1 0 1
1 1 1
样例输出
2
数据规模
对于100%100%的数据,保证2≤n≤1002≤n≤100,左上角右下角都是可以通行的。
 

思路 :

z最基本路径计数:这段代码定义了一个二维数组 a 来存储网格的信息,

dp 数组用来存储从左上角到当前位置的路径数量。

首先将 dp[1][1] 初始化为 1,表示从起点到起点的路径数量为 1。

接下来,遍历所有格子,如果当前格子可通行,

则从上方格子和左方格子累加路径数量,

dp[i][j] = dp[i - 1][j] + dp[i][j - 1]

,最后对结果取模输出即可。

而本题只需要再加上一个条件判断即可

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

int main()
{
	int n;int temp;
	cin>>n;
	int book[n+2][n+2];
	long long ans[n+2][n+2]={0};
	for(int i=1;i<=n;i++)
	{   
	for(int j=1;j<=n;j++)
		cin>>book[i][j];
		
	}
	for(int i=1;i<=n;i++)
	{
		if(book[1][i]==1)
		ans[1][i]=1;
		else
	    break;
		
	}
	
	
	
	
	
	
		for(int i=1;i<=n;i++)
	{
		if(book[i][1]==1)
		ans[i][1]=1;
		else
	    break;
		
	}
	for(int i=2;i<=n;i++)
	{
		for(int j=2;j<=n;j++)
		{
			if(book[i-1][j]!=0&&book[i][j-1]!=0)
			{
			ans[i][j]=ans[i-1][j]+ans[i][j-1];
			
			ans[i][j]=ans[i][j]%1000000007;
		}
			else if(book[i-1][j]!=0&&book[i][j-1]==0)
			ans[i][j]=ans[i-1][j];
			else if(book[i-1][j]==0&&book[i][j-1]!=0)
			ans[i][j]=ans[i][j-1];
		}
	}
	
	cout<<ans[n][n];
	
	
	
	
}

给定一个长度为 n� 的数组 a1,a2,…,an�1,�2,…,��,问其中的和最大的上升子序列。也就是说,我们要找到数组 p1,p2,…,pm�1,�2,…,��,满足 1≤p1<p2<⋯<pm≤n1≤�1<�2<⋯<��≤� 并且 ap1<ap2<⋯<apm��1<��2<⋯<���,使得ap1+ap2+⋯+apm��1+��2+⋯+���最大。

输入格式

第一行一个数字 n�。

接下来一行 n� 个整数 a1,a2,…,an�1,�2,…,��。

输出格式

一个数,表示答案。

样例输入

6
3 7 4 2 6 8

样例输出

21

数据规模

所有数据保证 1≤n≤1000,1≤ai≤1051≤�≤1000,1≤��≤105。

 

 

思路:

使用动态规划

dp[i] = max(dp[i], dp[j] + a[i]); 

dp[i] 表示以 a[i] 结尾的最大上升子序列的和

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

const int N = 1010;

int n;
int a[N];
int dp[N]; // dp[i] 表示以 a[i] 结尾的最大上升子序列的和

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    int res = 0; // 最终答案
    for (int i = 1; i <= n; i++)
    {
        dp[i] = a[i]; // 初始化为 a[i]
        for (int j = 1; j < i; j++)
        {
            if (a[i] > a[j])
                dp[i] = max(dp[i], dp[j] + a[i]); // 更新 dp[i],使得 dp[i] 表示以 a[i] 结尾的最大上升子序列的和
        }
        res = max(res, dp[i]); // 更新最终答案
    }

    cout << res << endl;

    return 0;
}

 

给定一个整数 n�。你需要对它做 m� 次操作。在一次操作中,你要将这个数的每一位 d� 替换成 d+1�+1。比如,19121912 在进行一次操作后将变成 2102321023。

请求出整数 n� 进行了 m� 次操作后的长度。答案可能很大,输出对 109+7109+7 取模后的结果。

输入格式

​ 第一行一个整数 t�,表示测试单元的个数。

​ 接下来 t� 行,每行有两个整数 n� 和 m�,表示最初的数字和进行多少次操作。

输出格式

​ 对于每个测试单元输出最终数字的长度,答案对 109+7109+7 取模。

样例输入

5
1912 1
5 6
999 1
88 2
12 100

样例输出

5
2
6
4
2115

数据规模

​ 所有数据保证 1≤t≤2⋅1051≤�≤2⋅105,1≤n≤1091≤�≤109,1≤m≤2⋅1051≤�≤2⋅105。

 思路:

动态规划来接,

状态转移方程有两种情况,

j=0~8是:f[i] [j-1]=f[i-1] [j];

j=9时是f[i] [9]=(f[i-1] [0]+f[i-1] [1])%MOD。

因为9加完后是10,位数就是1和0加起来。其余则和+1前的数一样。

最后我们以字符串形式读入数字,以数字形式读入操作次数m,

然后根据数字每位上的数,

将f[m] [j]累加起来即可,

注意要取模。

 

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
typedef pair<int, int>PII; 
const int MOD = 1e9 + 7;
const int N = 200010;
ll f[N+50][10];

int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 0; i <= 9; i++)f[0][i] = 1;
	for (int i = 1; i <= N; i++)
	{
		for (int j = 1; j <= 9; j++)f[i][j - 1] = f[i-1][j];
		f[i][9] = (f[i-1][1] + f[i-1][0]) % MOD;
	}
	while (n--)
	{
		char str[20];
		int m, res = 0;
		scanf("%s %d", &str, &m);
		int len = strlen(str);
		for (int i = 0; i < len; i++)
		{
			res += f[m][str[i] - '0'];
			res %= MOD;
		}
		cout << res << "\n";
	}
	return 0;
}

平面上给定了一些整点(横纵坐标均为整数的点),被称为 “魔法阵”。魔法少女派派想要在各魔法阵之间传送,每一次传送,她将使用下面的方式:

  1. 刚开始,派派已经位于某传送阵之上;
  2. 如果派派掌握一种魔法 (A,B)(�,�),其中 A,B�,� 均为整数。使用一次这个魔法可以让派派从任意整点 (X,Y)(�,�) 瞬间移动至 (X+A,Y+B)(�+�,�+�);
  3. 选择一种魔法并开始传送,在一次传送过程中可以使用多次该魔法,但在抵达下一个传送阵之前仅能使用这一种魔法

问派派至少需要掌握多少种魔法,才能在从任意魔法阵直接传送到任意魔法阵?

输入格式

第一行一个整数 N�。

接下来一行 N� 行,每行包含两个整数 Xi,Yi��,��, 表示每个魔法阵的坐标。

输出格式

一个数,表示答案。

样例1输入

3
1 1
4 5
1 4

样例1输出

6

解释: 任务是从 (1,1)(1,1) 传送至 (4,5)(4,5) 以及 (1,4)(1,4) 、从 (4,5)(4,5) 传送至 (1,1)(1,1) 以及 (1,4)(1,4) 、从 (1,4)(1,4) 传送至 (1,1)(1,1) 以及 (4,5)(4,5) 。

注意你不能使用 (0,3)+(3,1)(0,3)+(3,1) 的魔法从 (1,1)(1,1) 到达 (4,5)(4,5)。因为每次移动,你只能使用一种魔法。

当然,你可以学习 (0,1)(0,1),那样的话,从 (1,1)(1,1) 到达 (1,4)(1,4) 则需要使用 33 次 (0,1)(0,1) 魔法了。

样例2输入

3
1 1
2 2
1000000000 1000000000

样例2输出

2

数据规模

  • N∈[10,500]�∈[10,500]
  • Xi,Yi∈[0,109]��,��∈[0,109], 但保证坐标之间两两不同

 English 

 

 思路:

直接暴力就可以。

每次移动只能使用一种魔法,但可以重复使用,

魔法阵不是简单的两点之间的差值,而是差值的最简式,

即比例不变的情况下,魔法阵的两边值最小。

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

int main()
{
	
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	
	int n;
	cin>>n;
	pair<int,int> point[n+2];
	set<pair<int,int>> ans;
	for(int i=1;i<=n;i++)
	cin>>point[i].first>>point[i].second;
	for(int i=1;i<=n;i++)
	{
			for(int k=i+1;k<=n;k++)
			{
				int a=point[k].first-point[i].first;
				int b=point[k].second-point[i].second;
				
				int temp=__gcd(a,b);
				a/=temp;
				b/=temp;
				ans.insert({a,b});
			}
	}
	
	
	cout<<ans.size()*2<<endl;
	
	
	
}

 

对于一个长度为 n� 的0101序列 a1,a2,…,an�1,�2,…,��。

你可以执行以下操作任意多次:

  • 选择两个下标 1≤i,j≤n(i≠j)1≤�,�≤�(�≠�)。

  • 记x=ai xor aj�=�� xor �� , y=ai or aj�=�� or �� , 其中 xorxor 表示按位异或 , oror 表示按位或。

  • 然后令 ai=x,aj=y��=�,��=� 或 ai=y,aj=x��=�,��=�。

给定两个0101序列 s,t�,� , 请你判断是否可以通过有限次(可以为00次)操作将序列 s� 变为 t�。

输入格式

第一行一个整数 t� , 表示数据的组数(1≤t≤103)(1≤�≤103)。接下来 t� 组数据:

每组第一行一个0101字符串 s(1≤|s|≤103)�(1≤|�|≤103),每组第二行一个0101字符串 t(1≤|t|≤103)�(1≤|�|≤103)。

注意:|s||�| 可能不等于 |t||�|。

输出格式

如果可以通过有限次(可以为00次)操作将序列 s� 变为 t� , 输出 YES , 否则输出 NO

样例输入

2
001
011
11
101

样例输出

YES
NO

样例解释

第一组数据选择 i=2,j=3�=2,�=3 , 那么 x=1,y=1�=1,�=1 , 接着令 ai=x,aj=y��=�,��=� 即可得到 t� 序列。

第二组数据 |s|=2,|t|=3|�|=2,|�|=3 显然无法满足要求。

思路:因为1与0能生出1,而1 1又能生出0,

所以一位一位的考虑便能一直生出0与1,但是最后一位的1最后会留下来,

它与任何位数上组合也就顶多算是交换位置或者有多出一个1,

所以一定会有一个1留下来。那么我们只用考虑1的个数即可。

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

int main()
{ios_base::sync_with_stdio(false);
cin.tie(NULL);
	
int n;
string a,b;

cin>>n;

for(int i=0;i<n;i++)
{   int flag=0,ca=0;
	cin>>a>>b;
	if(a.length()!=b.length())
	{
		cout<<"NO"<<endl;
		
	}
	else
	{
		for(int k=0;k<b.length();k++)
		{
			if(b[k]=='1')
			{
				flag=1;
				break;
			}
    	}   
    	
    	
    	
    	for(int k=0;k<a.length();k++)	
				{
					if(a[k]=='1')
					{
					
						ca=1;
						break;
					}
					
				}
			
		if(flag==0)
		{
				
				if(ca==1)
				cout<<"NO"<<endl;
				else
				cout<<"YES"<<endl;
				
				
				
				
				
		}
		else
		{
			if(ca==1)
			cout<<"YES"<<endl;
			else
			cout<<"NO"<<endl;
		}
			
	}
	
	
	
}

}

 

 

我们称一个字符串为好字符串,指这个字符串中只包含01

现在有一个好字符串,求这个字符串中1恰好出现k�次的子串有多少个。

输入格式

第一行给出一个数字k�,表示子串中1的个数。

第二行给出好字符串。

输出格式

输出一个整数,表示好字符串中有多少个符合条件的子串

数据范围

0≤k≤106, |s|≤1060≤�≤106, |�|≤106

样例输入1

1
1010

样例输出1

6

样例输入2

2
01010

样例输出2

4

既然是子串,那就说明是连续的,且字符串除了0就是1,

那么我们可以用前缀和的思路来写,

这样问题就变成了,区间和为k的情况有多少。

我们计算子串的前缀和数组,

并把相同前缀和的数量用哈希表记录下来。

每一个前缀和为sum的位置,

都能和所有前缀和为sum-k的位置形成好子串,

所以我们计数器记录的是前缀和为sum的数量*前缀和为sum-k的数量。

最后只要把计数器输出即可。
 

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

int main()
{/*ios_base::sync_with_stdio(false);
cin.tie(NULL);*/
	
int n;
long long sum=0;
cin>>n;
int a[1000007]={0};
string b;
cin>>b;
int flag=0;

for(int i=0;i<b.length();i++)
{
	if(b[i]=='1')
	flag++;
	else
	a[flag]++;
}


if(n!=0)
{
for(int k=0;k<=flag-n;k++)
{
	sum=sum+(a[k]+1)*(a[k+n]+1);
}

}




else
{
	for(int k=0;k<=flag;k++)
	{
		
		if(a[k]!=0)
		{
			for(int j=1;j<=a[k];j++)
			sum=sum+j;
		}
	}
}


cout<<sum;
}

 

 

现在有一个栈,有 n� 个元素,分别为 1,2,…,n1,2,…,�。我们可以通过 push 和 pop 操作,将这 n� 个元素依次放入栈中,然后从栈中弹出,依次把出栈的元素写下来得到的序列就是出栈序列。

比如 n=3�=3,如果执行 push 1, push 2, pop, push 3, pop, pop,那么我们 pop 操作得到的元素依次是 2,3,12,3,1。也就是说出栈序列就是 2,3,12,3,1。

现在给定一个合法的出栈序列,请输出一个合法的由 push 和 pop 操作构成的操作序列。这里要求 push 操作一定是按 1,2,…,n1,2,…,� 的顺序。

输入格式

第一行一个整数 n�。接下来一行 n� 个整数,表示出栈序列。

输出格式

输出 2n2� 行,每行一个 push 或 pop 操作,可以证明一个出栈序列对应的操作序列是唯一的。

 

样例输入1

3
2 3 1

样例输出1

push 1
push 2
pop
push 3
pop
pop

样例输入2

5
1 3 5 4 2

样例输出2

push 1
pop
push 2
push 3
pop
push 4
push 5
pop
pop
pop

数据规模

对于 100%100% 的数据,保证 1≤n≤1000001≤�≤100000,输入一定是个合法的出栈序列。

思路:vector可以向中间插入,所以我们用vector来写。

vector用法:

1. 在指定位置插入:v.insert(v.begin()+x , k),x-1是在vector的第x个数前面插入k.                               x是在第x后面插入k。(因为相当于又在0后面数了x个)

2.删除指定位置的数:v.erase(v.begin()+x),删除第x+1个数。(begin会占住0位)

 3.删除指定区间:v.erase(v.begin()+i,v.begin()+j),删除区间 [i,j-1] 的数。

   4.查询指定位置:直接用下标访问。记住vector的下标是从0开始的。

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

int main()
{

	ios_base::sync_with_stdio(false);
		cin.tie(NULL);

	
	int n;
	cin>>n;
int arr[n+5];
int maxx=1;
for(int i=1;i<=n;i++)
{
	cin>>arr[i];
	
}



for(int i=1;i<=n;i++)
{
	if(arr[i]>=maxx)
	{
		for(int k=maxx;k<=arr[i];k++)
		cout<<"push "<<k<<"\n";
		cout<<"pop"<<"\n";
	maxx=arr[i]+1;
	}
	else
	{
		cout<<"pop"<<"\n";
	}
}
	
	
	
}

 

你有一个序列,现在你要支持几种操作:

  • insert x y,在从前往后的第x�个元素后面插入y�这个数。如果x=0�=0,那么就在开头插入。

  • delete x,删除从前往后的第x�个元素。

  • query k,询问从前往后数第k�个元素是多少。

输入格式

第一行一个整数m�,表示操作个数。

接下来m�行,每行一个上面所述的操作。

输出格式

输出若干行,对于每个查询操作,输出答案。

样例输入

10
insert 0 1
insert 1 2
query 1
query 2
insert 0 3
query 1
delete 1
query 1
insert 1 4 
query 2

样例输出

1
2
3
1
4

数据规模

对于100%100%的数据,保证m≤103�≤103。

对于insert操作,保证1≤y≤1091≤�≤109。

对于所有操作,保证位置不会超出当前序列的长度。

 

使用stl即可

#include<bits/stdc++.h>
using namespace std;
​
vector<int> k;
string op;
int m;
​
int main(){
    cin >> m;
     while(m--){
        string op;
        cin >> op;
        if(op == "insert"){
            int x,y;cin >> x >> y;
            k.insert(k.begin()+x,y);//插入
        }
        if(op == "query"){
            int x;in >> x;
            cout << k[x-1] << endl;
        }
        if(op == "delete"){
            int p;cin >> p;
            k.erase(k.begin()+p-1);//删除
        }
    }
​
}

 

您将获得一个 n×n�×� 的网格,网格中每个正方形的颜色为黑色或白色。如果满足以下所有条件,则网格是正确的:

  • 每行的黑色方块数与白色方块数相同。

  • 每列的黑色正方形数与白色方块数相同。

  • 没有行或列具有 33 个及以上相同颜色的连续正方形。

给定网格,确定它是否正确。

输入格式

第一行一个数字 n�(2≤n≤242≤�≤24), 并且数字 n� 是偶数。

接下来 n� 行,每行包含一个长度为n�的由字符BW组成的字符串,代表网格正方形的颜色。

输出格式

如果网格正确,请打印数字 11 在一行上。否则,请打印数字 00 在一行上。

样例输入

4
WBBW
WBWB
BWWB
BWBW

样例输出

1

 

关键在于状态的维护

读入一个色块,有一下两种情况

(1)与当前连续色块颜色一致:色块连续数++

(2)与当前连续色块颜色不一致:修改当前连续色块颜色,初始化色块连续数为1 


 

 

#include<bits/stdc++.h>
using namespace std;
int main(){ios_base::sync_with_stdio(false);
cin.tie(NULL);
	int n;
	cin>>n;int flag=0;char ac;
	int a[n+2][n+2];
	for(int i=1;i<=n;i++)
      {
		for(int k=1;k<=n;k++)
	   {
		
		cin>>ac;
		if(ac=='W')
		a[i][k]=1;
		else 
		a[i][k]=0;
		
	 	
       }
    }
    
    
    
    
    for(int i=1;i<=n;i++)
      {  int num1=0,num0=0;
		                  for(int k=1;k<=n;k++)
	                      {
	                     	if(a[i][k]==1)
		                    num1++;
		                    else 
		                       num0++;
                            }
       if(num1!=num0)
       {
       	flag=1;
		break;
	   }
       
       
       
                                     for(int k=1;k<=n-2;k++)
	                               {
		                              if(a[i][k]==a[i][k+1]&&a[i][k]==a[i][k+2])
	                                    	{
			                                flag=1;
		                                    break;
		                                      }
                                    }
       
       if(flag==1)
       {
       	
		break;
	   }
       
       
       
       
       
       
    }
    
    
    
    
    
    
    
    
    
    
    
      
    for(int k=1;k<=n;k++)
    
    
    
      { 
	   if(flag==1)
       {
       	
		break;
	   }
       
	  
	  
	  
	  
	  
	  
	  
	  
	   int num1=0,num0=0;
		                  for(int i=1;i<=n;i++)
	                      {
	                     	if(a[i][k]==1)
		                    num1++;
		                    else 
		                       num0++;
                            }
       if(num1!=num0)
       {
       	flag=1;
		break;
	   }
       
       
       
                                     for(int i=1;i<=n-2;i++)
	                               {
		                              if(a[i][k]==a[i+1][k]&&a[i+2][k]==a[i][k])
	                                    	{
			                                flag=1;
		                                    break;
		                                      }
                                    }
       
       if(flag==1)
       {
       	
		break;
	   }
       
       
       
       
       
       
    }
    
    
    
    
     if(flag==1)
       {
       cout<<0;
	   }
	   else
	   cout<<1;
       
    
    
	
}

​ Polycarp 有一个长度为 n� 的数组 a1,a2,...,an�1,�2,...,��(n� 是偶数)。Polycarp 还得到了一个正整数 k�,他开始对数组 a� 做如下操作:选择一个下标 i (1≤i≤n)� (1≤�≤�) 使 ai�� 减去 k�。

​ 在 Polycarp 进行若干次操作后(可能 00 次),数组 a� 中的所有数都变成相同的了。请你找到最大的符合要求的 k�,如果 k� 可以为任意大,请输出 −1−1。

输入格式

​ 第一行一个整数 t�,表示测试单元的个数。

​ 接下来每个测试单元有两行。第一行包含一个偶数 n�。第二行包含 n 个整数 a1,a2,...,an�1,�2,...,��。

输出格式

​ 对于每个测试单元输出单独一行一个整数 k (k≥1)� (�≥1) —— Polycarp 能用来对数组进行操作的最大的数,或者 −1−1 —— 如果 k� 能任意大的话。

 

这个题其实就是找出除了最小值之外,其余值到最小值的距离的最大公约数,

求全部的公约数:就是将数组全部遍历一遍即可,

得到最后的gcd即可。当数组中的数全部相同时gcd为0。

#include<bits/stdc++.h>
using namespace std;
int main(){ios_base::sync_with_stdio(false);
cin.tie(NULL);
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int n1;cin>>n1;int ans=100000006;int temp;
		set<int> s;
		
		int arr[n1+4],res[n1+4];
		for(int k=0;k<n1;k++)
		
		{
			cin>>temp;
			s.insert(temp);
			
		}
		
		int num=s.size();
		
		if(num>=2)
	{
			auto it=s.begin();
	for(int k=0;k<num;k++)
	{
		arr[k]=*it;
		it++;
	}
	if(num==2)
	{
		cout<<arr[1]-arr[0]<<endl;
	}
	
	else
	{
	
	for(int k=0;k<num-1;k++)
	{
		res[k]=arr[k+1]-arr[k];
	}
		
		
	sort(res,res+num-1);
	
		for(int j=1;j<num-1;j++)
		{
			ans=min(ans,__gcd(res[0],res[j]));
if(ans==1)
break;
		}
		cout<<ans<<endl;
	}
	
}
	
	
	else 
	{
		cout<<-1<<endl;
	}
	

	
}


}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值