文章目录
VScode配置包
知识点
BFS广度优先搜索
广度优先搜索(Breadth-First Search, BFS)是一种用于遍历或搜索树或图的算法。
这个算法从一个节点开始,探索该节点的所有直接邻居,然后再对每一个邻居节点进行同样的操作,直到找到目标节点或遍历完所有可达的节点。
BFS通常使用队列(Queue)来实现。
bfs和dfs的区别:
dfs
往一个方向深搜后返回再搜bfs
往多个方向广搜(水波)
基本步骤
- 初始化:选择一个起始节点,将其放入队列中。
- 循环:当队列非空时,执行以下步骤:
- 从队列中移除一个节点(通常是队首节点)。
- 访问该节点(例如,打印节点值或进行其他处理)。
- 将该节点的所有未访问过的直接邻居节点加入队列中。
- 结束:当队列为空时,算法结束。
基本作用
- BFS在搜索最短路径时非常有用,因为它总是先访问起始节点附近的节点。
- BFS在无权图中特别有效,但在有权图中,如果边的权重不同,则可能需要使用其他算法(如Dijkstra算法)来找到最短路径。
- BFS的时间复杂度依赖于图的表示和图的结构。在最坏的情况下(图是完全连接的),时间复杂度为O(V + E),其中V是顶点数,E是边数。在最好的情况下(图是线性的),时间复杂度为O(V)。
- BFS的空间复杂度主要由队列决定,最坏情况下为O(V),因为所有节点都可能被加入队列中。
样例:波浪形扩散原理
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, vis[1001][1001], dist[1001][1001];
struct point{
int x, y;
};
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};//上下左右
signed main(){
cin >> n >> m;
queue<point> q;
q.push({1, 1}); //起点
vis[1][1] = 1;
dist[1][1] = 0;
while(!q.empty()){
point t = q.front();
q.pop();
for(int i=0;i<4;i++){
point s;
s.x = t.x + dx[i];
s.y = t.y + dy[i];
if(s.x <= 0 || s.y <= 0 || s.x > n || s.y > m) continue;
if(vis[s.x][s.y] == 1) continue;
vis[s.x][s.y] = 1;
dist[s.x][s.y] = dist[t.x][t.y] + 1;
q.push(s);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout << dist[i][j] << " \n"[j==m];
}
}
return 0;
}
样例:走迷宫营救
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
const int maxn = 1e6 + 100;
const double eps = 1e-5;
//上下左右
int dx[] = { 0,0,-1,1 };
int dy[] = { -1,1,0,0 };
int mapp[100][100], vis[100][100];
int ok = 0;
struct point {
int x, y;
int step;
};
queue<point> s;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int n, m; cin >> n >> m;
//输入地图
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> mapp[i][j];
}
}
int startx, starty, endx, endy;
cin >> startx >> starty >> endx >> endy;
//初始化起点并入队
point start; //结构体
start.x = startx, start.y = starty, start.step = 1;
s.push(start);
vis[startx][starty] = 1;//vis 打标记,记录已经走过的点
//go
while (!s.empty()) {
int x = s.front().x, y = s.front().y;
s.pop();
if (x == endx && y == endy) {
ok = 1;
cout << s.front().step << endl;
break;
}
for (int choose = 0; choose <= 3; choose++) {
int tx = x + dx[choose];
int ty = y + dy[choose];//方向
if (mapp[tx][ty] == 0 && vis[tx][ty] == 0) {
point tmp;
tmp.x = tx;
tmp.y = ty;
tmp.step = s.front().step + 1;
s.push(tmp);
vis[tx][ty] = 1;
}
}
}
if (ok == 0) {
cout << "no ans" << endl;
}
return 0;
}
动态规划
动态规划(Dynamic Programming, DP)是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。在C++中实现动态规划通常涉及定义一个或多个数组(或向量)来存储子问题的解,以避免重复计算。
定义
动态规划通过把原问题分解为相对简单的子问题的方式求解复杂问题。它通常涉及以下几个关键步骤:
- 定义状态:将问题分解为一系列子问题,并定义状态来表示这些子问题的解。
- 状态转移方程:找出状态之间的关系,即如何从已知状态推导出新的状态(或解)。
- 初始化:确定初始状态的值。
- 计算顺序:确定计算状态的顺序,通常是自底向上(从简单到复杂)的顺序。
- 存储结果:使用数组、向量或其他数据结构来存储中间结果,以便后续使用。
语法
由于动态规划是一种算法设计思想,而不是具体的语法结构,因此它没有特定的语法。但是,在C++中实现动态规划时,通常会使用到以下语法元素:
- 数组(或
std::vector
):用于存储状态(即子问题的解)。 - 循环(如
for
、while
):用于遍历状态空间,计算状态转移方程。 - 条件语句(如
if
、else
):用于处理特殊情况或边界条件。 - 函数:将动态规划的逻辑封装在函数中,以便复用或测试。
用途
动态规划广泛应用于各种领域,特别是在计算机科学中,用于解决优化和计数问题。以下是一些常见的应用场景:
- 优化问题:如最短路径问题、最长公共子序列(LCS)、背包问题等。
- 计数问题:如不同路径的数量、排列组合问题等。
- 决策过程:如编辑距离、字符串匹配问题等。
示例
下面是一个使用C++实现的动态规划经典问题——斐波那契数列(Fibonacci Sequence)的示例。斐波那契数列是这样一个数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …,其中每个数是前两个数的和。
斐波那契数列的C++实现(动态规划)
#include <iostream>
#include <vector>
using namespace std;
// 动态规划求解斐波那契数列
int fibonacciDP(int n) {
if (n <= 0) return 0;
if (n == 1) return 1;
// 创建一个数组来存储斐波那契数列的值
vector<int> dp(n + 1, 0);
dp[1] = 1; // 初始化第一个值
// 从第二个数开始计算
for (int i = 2; i <= n; ++i) {
dp[i] = dp[i - 1] + dp[i - 2]; // 动态规划的核心递推公式
}
return dp[n];
}
int main() {
int n;
cout << "请输入n的值(斐波那契数列的第n项): ";
cin >> n;
cout << "斐波那契数列的第" << n << "项是: " << fibonacciDP(n) << endl;
return 0;
}
在这个例子中,我们使用了vector<int>
来存储斐波那契数列的值,以避免重复计算。通过从第二项开始迭代计算,直到第n项,我们得到了整个数列的解。这种方法的时间复杂度是O(n),空间复杂度也是O(n),因为我们使用了一个大小为n+1的数组来存储中间结果。
动态规划的应用非常广泛,包括但不限于背包问题、最长公共子序列(LCS)、最短路径问题等。每种问题都有其特定的状态定义和转移方程,但基本思想都是类似的:将大问题分解为小问题,并存储已解决的小问题的答案,以避免重复计算。
01背包&&完全背包
① 01背包:每件物品最多使用一次(只能使用0次或1次)
(一)状态表示 f(i j)
- 集合:只考虑前i个物品,且总体积不大于i的所有选法。
- 属性:Max、Min、数量
(二)状态计算-→集合划分-→f[i,j]= Max( f[i-1,j],f[i-1,j-V[i]]+ W[i])
② 完全背包:每件物品有无限个
(一)状态表示 f(i,j)
- 集合:只考虑前i个物品,且总体积不大于i的所有选法
- 属性:Max、Min、数量
(二)状态计算–→集合划分–→f[i,j]= Max( f[i-1,j],f[i, j-V[i]]+ W[i])
01背包问题
有
N
N
N件物品和一个容量是
V
V
V的背包,每件物品只能使用一次。
第
i
i
i件物品的体积是
V
i
Vi
Vi,价值是
W
i
Wi
Wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
//先输入 n m
4 5
1 2
2 4
3 4
4 5
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1010;
int n, m;
int v[N], w[N];
int f[N];
int main(){
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> v[i] >> w[i];
}
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){ //从大到小循环
f[j] = max(f[j], f[j-v[i]] + w[i]);
}
}
cout << f[m] << endl;
return 0;
}
解题集
B3635 硬币问题
#include<iostream>
#include<cstdio>
using namespace std;
int n, f[1000000];//用f数组存放数量
/*
f[0]=0;
f[1]=f[0]+1=1;
f[2]=f[1]+1=2;
*/
int main(){
cin >> n; //n元
for(int i=1;i<=n;i++){ //从最底层判断开始
if(i >= 11){ //i>=11,可以用一张11元钱的替换
f[i] = min(f[i-1], min(f[i-5],f[i-11])) + 1; //钱币数量叠加(最小)
}else if(i>=5){ //i=5~10,可以用一张5元钱的替换5张1元钱的
f[i]=min(f[i-1],f[i-5])+1; //钱币数量叠加(最小)
}else{ //i=1~4,只能用1元钱的
f[i]=f[i-1]+1; //钱币数量叠加
}
}
cout<<f[n]<<endl;//f[n]代表凑出n块钱需要的最少钱币数
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
const int maxn = 1e6 + 100;
const double eps = 1e-5;
signed main() {
int a[3] = { 1,5,11 };
int n; cin >> n;
vector<int>dp(n + 1, 0x3f3f3f3f);//dp(长度,值)
//0x3f3f3f3f 是一个很大的数 默认需要无穷的金币
dp[0] = 0;//需要的金币的数量
for (int i = 0; i < 3; i++) {//遍历每一种金币
for (int j = a[i]; j <= n; j++) {// j 是 钱的sum
dp[j] = min(dp[j - a[i]]+ 1, dp[j]) ;//类似记忆
}
}
cout << dp[n] << endl;//输出组成金额n 所需要的最少金币的数量
return 0;
}
//也可以使用 BFS
P10250 [GESP样题 六级] 下楼梯
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int n;
cin >> n;
vector<int> dp(n + 1, 0);
dp[0] = 1;
for (int i = 0; i <= n;i++){
for (int j = 1; j <= 3;j++){
if( i+j > n) break;
dp[i + j] += dp[i];
}
}
cout << dp[n] << endl;
return 0;
}
过河卒
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
int n, m, x, y, dp[1001][1001];
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
cin >> n >> m >> x >> y;
dp[0][0] = 1;
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= m; j++)
{
if(i == 0 && j == 0)
continue;
if(i != 0)
dp[i][j] += dp[i - 1][j];
if(j != 0)
dp[i][j] += dp[i][j - 1];
if(i == x && j == y)
dp[i][j] = 0;
else if(abs(i-x)==1&&abs(j-y)==2)
dp[i][j] = 0;
else if(abs(i-x)==2&&abs(j-y)==1)
dp[i][j] = 0;
}
}
cout << dp[n][m] << endl;
return 0;
}
母牛的故事
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
vector<int> dp(56);
dp[1] = 1, dp[2] = 2, dp[3] = 3,dp[4]=4; //第1年到第4年都只有一只老母牛在生产一只小母牛
//往后的年份中,计算上一年的母牛数和三年前的母牛数(今年是第四年,他们已经长大了)
for(int i=5;i<=55;i++){
dp[i] = dp[i-1] + dp[i-3];
}
int n;
while(cin >> n&&n!=0){
cout << dp[n] << endl;
}
return 0;
}
超级楼梯
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<int> dp(n + 1, 0);
dp[1] = 1;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= 2; j++)
{
if (i + j > n) break;
dp[i + j] += dp[i];
}
}
cout << dp[n] << endl;
}
return 0;
}
折线分割平面
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
vector<int> dp(10001);
dp[0]=1;
for(int i=1;i<=10000;i++){
dp[i] = ((i-1)*2-1)*2 + dp[i-1]+3;
}
int c;
cin >> c;
while(c--){
int n;
cin >> n;
printf("%d\n", dp[n]);
}
return 0;
}
Coin Change
假设有5种硬币:50美分、25美分、10美分、5美分和1美分。我们想要用这些硬币来支付给定金额的钱。
例如,如果我们有11美分,那么我们可以用1个10美分的硬币和1个1美分的硬币来支付,或者用2个5美分的硬币和1个1美分的硬币来支付,或者用1个5美分的硬币和6个1美分的硬币来支付,或者用11个1美分的硬币来支付。因此,用上述硬币支付11美分有4种不同的方式。请注意,我们将1种支付0美分的方式也计算在内。
编写一个程序,找出用上述5种硬币支付任何金额的钱的不同方式的总数。您的程序应能处理多达100种硬币。
输入:
输入文件包含任意数量的行,每行包含一个金额(≤250),以美分为单位。
输出:
对于每条输入行,输出一行,包含用上述5种硬币支付该金额的不同方式的数量。
Input
11
26
Output
4
13
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
int a[5] = {1, 5, 10, 25, 50}; //表示5种硬币各自的价值
int dp[110][260]; //表示dp[i][v],用i个硬币凑成价值为v的方法数
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int n;
while (cin >> n){
memset(dp, 0, sizeof(dp)); //初始化dp数组全变为0
dp[0][0] = 1; //边界,用0个硬币凑成0美分,有1种方法
for (int i=0;i<5;i++){ //5种硬币的价值
for (int k=1;k<=100;k++){ //k个硬币
for (int v=a[i];v<=n;v++){
dp[k][v] += dp[k-1][v-a[i]];//状态转移方程
}
}
}
int ans=0;
for (int i=0;i<=100;i++){
ans += dp[i][n];
}
cout << ans << endl;
}
return 0;
}
AtCoder Janken 3
问题陈述
高桥和青木玩了
N
N
N 次剪刀石头布。注:在这个游戏中,石头赢剪刀,剪刀赢纸,纸赢石头。
青木的动作由长度为{624444356}的字符串
S
S
S 表示,字符串由 “R”、"P "和 "S "组成。
S
S
S 中的
i
i
i -th字符表示青木在
i
i
i -th对局中的棋步:R "表示 “石头”,"P "表示 “纸”,"S "表示 “剪刀”。
高桥的棋步满足以下条件:
- 高桥从未输给过青木。
- 对于 i = 1 , 2 , … , N − 1 i=1,2,\ldots,N-1 i=1,2,…,N−1 ,高桥在 i i i /th对局中的棋步与他在 ( i + 1 ) (i+1) (i+1) /th对局中的棋步不同。
请确定高桥的最大胜局数。
可以保证存在一个满足上述条件的高桥下棋顺序。
限制因素
- 1 ≤ N ≤ 2 × 1 0 5 1\leq N\leq2\times10 ^ 5 1≤N≤2×105
-
S
S
S 是长度为
N
N
N 的字符串,由
R
、P
和S
组成。 - N N N 是一个整数。
输入
输入内容由标准输入法提供,格式如下
N
N
N
S
S
S
输出
打印高桥可能赢得的最大局数。
输入样本 1
6
PRSSRS
样本输出 1
5
在六局剪刀石头布游戏中,青木分别玩了剪刀石头布、剪刀石头布、剪刀石头布和剪刀石头布。
高桥可以玩剪刀、布、石头、剪刀、布和石头,赢得第一、第二、第三、第五和第六局。
对于高桥来说,不存在满足条件并赢得所有六盘棋的下棋顺序,因此打印
5
5
5 。
输入样本 2
10
SSSSSSSSSS
输出示例 2
5
输入样本 3
24
SPRPSRRRRRPPRPRPSSRSPRSS
输出示例 3
18
解题代码
略
Charm Bracelet S
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
int n, m;
int v[N], w[N];
int f[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> v[i] >> w[i];
}
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){ //从大到小循环
f[j] = max(f[j], f[j-v[i]] + w[i]);
}
}
cout << f[m] << endl;
return 0;
}
NASA的食物计划
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
int hi[1000],ti[1000],ki[1000];
int dp[10000][10000];
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int hmax, tmax,n;
cin >> hmax >> tmax >> n;
for (int i = 1; i <= n;i++){
cin >> hi[i] >> ti[i] >> ki[i];
}
for (int i = 1; i <= n;i++){
for (int j = hmax; j >= hi[i]; j--){
for(int z = tmax;z >= ti[i];z--){
dp[j][z] = max(dp[j][z], dp[j - hi[i]][z - ti[i]] + ki[i]);
}
}
}
cout << dp[hmax][tmax] << endl;
return 0;
}
A+B Problem(再升级)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
int dp[10010];
bool isPrime(int x) {
if (x < 2)
{
return false;
}
//试除法
for (int i = 2; i <= x/i; i++)
{
if (x % i == 0) {
return false;
}
}
return true;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int n;
cin >> n;
dp[0] = 1;
for (int i = 2; i <= n; i++){
if(!isPrime(i))continue;
for (int j = 0; j <= n; j++){
if(j+i>n)
break;
dp[j + i] += dp[j];
}
}
cout << dp[n] << endl;
return 0;
}
小书童——刷题大军
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
int a[1000],t[1000],s[1000];
vector<int> dp(1000, 0);
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int n, m, k, r;
cin >> n >> m >> k >> r;
for (int i = 1; i <= n;i++){cin >> a[i];}
for (int i = 1; i <= m;i++){cin >> t[i];}
for (int i = 1; i <= m;i++){cin >> s[i];}
for (int i = 1; i <= m;i++){
for (int j = r; j >= t[i];j--){
dp[j] = max(dp[j], dp[j - t[i]] + s[i]);
}
}
for (int i = 0; i <= r; i++) {
if (dp[i] >= k) {
r -= i; break;
}
}
int ans = 0;
sort(a+1, a+1+n);
for (int i = 1; i <= n; i++){
if(r-a[i]>=0){
ans++;
r -= a[i];
}
else
break;
}
cout << ans << endl;
return 0;
}
浙工院养奶牛
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
vector<int> dp(56);
dp[1] = 1, dp[2] = 1, dp[3] = 1,dp[4]=2,dp[5]=3; //第1年到第4年都只有一只老母牛在生产一只小母牛
//往后的年份中,计算上一年的母牛数和三年前的母牛数(今年是第四年,他们已经长大了)
for(int i=6;i<=55;i++){
dp[i] = dp[i-1] + dp[i-3];
}
cout << dp[50] << endl;
return 0;
}
学长会旋转
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int n,k;
cin >> n >> k;
int a[n + 1][n + 1],b[n + 1][n + 1];
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n;j++){
cin >> a[i][j];
}
}
k = k % 4;
if(k==0){
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n;j++){
cout << a[i][j]<<" ";
}
cout << endl;
}
return 0;
}
if(k==1){
for (int i = 1; i <= n; i++){
for (int j = n; j >= 1;j--){
cout << a[j][i]<<" ";
}
cout << endl;
}
return 0;
}
if(k==2){
for (int i = n; i >= 1; i--){
for (int j = n; j >= 1;j--){
cout << a[i][j]<<" ";
}
cout << endl;
}
return 0;
}
if(k==3){
for (int i = n; i >= 1; i--){
for (int j = 1; j <= n;j++){
cout << a[j][i]<<" ";
}
cout << endl;
}
return 0;
}
return 0;
}
学长的数(1)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl "\n"
#define fi first
#define se second
#define mod3 998244353
#define mod7 1000000007
const int N = 1e6 + 10;
const double eps =1e-4;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int n;
cin >> n;
int x = 1, ans = 0;
while (x <= n){
ans = x;
x = x*2 +1;
}
cout << ans;
return 0;
}