【算法】GOJ 1053 还是A+B

本文详细解析1053题的解题思路,并介绍C++string库函数的应用,包括字符串长度获取、构造函数、插入与复制操作及字符串与整型的转换方法。

1053也是一道简单题,用整形数组也是可以做出来的。不过我主要用它来熟悉C++ string库函数的一些用法。
1053题目:
还是A+B
Problem Description:
读入两个小于10000的正整数A和B,计算A+B。需要注意的是:如果A和B的末尾K(不超过8)位数字相同,(位数不足前导补0)请直接输出-1。
Input:
测试输入包含若干测试用例,每个测试用例占一行,格式为"A B K",相邻两数字有一个空格间隔。当A和B同时为0时输入结束,相应的结果不要输出。
Output:
对每个测试用例输出1行,即A+B的值或者是-1。
Sample Input:
1 2 1
11 21 1
108 8 2
36 64 3
0 0 1
Sample Output:
3
-1
-1
100

主要用到的string中的函数有:
1.获取string的长度,可以用str.size()str.length().(注意两者返回的是unsign int ,它比int 高级。 unsign int 类型与int 类型的运算该强制转换就强制转换,以避免不必要的错误,比如unsign i=5;cout<<(i-6)%7 << endl;//结果为3。

/#不建议使用strlen(char * )来获取string 的长度,因为strlen接受的参数是char *,需要先将string转换成char数组,即strlen(str.c_str()),c_str()是其一个成员函数,表示将string转换成char数组,这样有点多此一举#/

2.string类的构造函数。这里就只先介绍本题用到的(以后遇到相应的题目,再进行补充): string str(size_type n,char c)。说明:创建一个包含n个元素的string对象str,其中每个元素都被初始化为字符c。

3.string类的插入操作函数。同样insert函数具有不同的重载函数。这里同样只介绍本题用到的: s.insert(pos, str),将str的拷贝插入到s的pos位置,返回s;注意是返回s,也就是s本身已经发生了变化

4.string类的复制操作。本题使用了str.substr(pos, n)。函数说明:返回str中从pos(默认为0)开始的,有n个字符组成的s的子串的拷贝;注意返回的string 类型,str本身不发生变化。

5.int与string的相互转换。这里暂且只先介绍string转int。
方法一:
使用C语言< stdlib.h>中的*atoi(str.c_str())函数,需要先将string类型转为char 数组指针。
方法二:
使用C++11中的
stoi(str)**函数,比如 int a=stoi(str); stoi可以转换为十进制、八进制、十六进制和二进制数字,不过在codeblocks上,我选择C++11标准编译器却编译错误,好像只能用VS了。

6.string的compare的使用,这里先介绍简单比较两个字符串是否相等。str1.compare(str2),返回值为正、0、负。0代表相等。
(不足之处,欢迎大家补充!)

AC代码:

#include<iostream>
#include<string>
#include<stdlib.h>//atoi函数
using namespace std;
void Changefun(string &str,int k)
{//处理函数
     if(str.size()<k)
        {
            int len=k-str.size();
            string N_B(len,'0');
            str.insert(0, N_B);
        }
}
int main()
{
    string A;
    string B;
    int k;
    while(cin>>A>>B>>k)
    {
        if(A=="0"&&B=="0")
            break;
        //是否需要补充位数
        Changefun(B,k);
        Changefun(A,k);
        //比较
        if(((A.substr(A.size()-k,k)).compare(B.substr(B.size()-k,k)))==0)
            cout<<-1<<endl;
        else
        {//转换为int类型
            int numA = atoi(A.c_str());
            int numB = atoi(B.c_str());
            cout<<numA+numB<<endl;
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,代码仅用于交流和学习!转载请注明出处!

是对于这道题,这个代码的做法是如何推导出来的 # AT_agc037_b [AGC037B] RGB Balls ## 题目描述 有 $3N$ 个带颜色的球,每个球编号从 $1$ 到 $3N$。每个球的颜色由长度为 $3N$ 的字符串 $S$ 表示,第 $i$ 个球的颜色为 $S_i$,若 $S_i$ 为 `R` 则为红色,`G` 为绿色,`B` 为蓝色。红色、绿色、蓝色的球各有 $N$ 个。 高桥君要将这 $3N$ 个球分给 $N$ 个人,使得每个人都能分到一个红球、一个绿球一个蓝球。此外,分配还需满足以下条件: - 对于第 $j$ 个人,设他拿到的球的编号按升序为 $a_j < b_j < c_j$。 - 使得 $\sum_j (c_j - a_j)$ 的值尽可能小。 计算高桥君有多少种分配球的方法。由于答案可能很大,输出对 $998244353$ 取模的结果。若存在某个人分到的球的集合不同,则认为两种分配方法不同。 ## 输入格式 输入通过标准输入给出,格式如下: > $N$ $S$ ## 输出格式 输出高桥君分配球的方法数对 $998244353$ 取模的结果。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 RRRGGGBBB ``` ### 输出 #1 ``` 216 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 5 BBRGRRGRGGRBBGB ``` ### 输出 #2 ``` 960 ``` ## 说明/提示 ## 限制条件 - $1 \leq N \leq 10^5$ - $|S| = 3N$ - $S$ 仅由 `R`、`G`、`B` 组成,且每种颜色在 $S$ 中各出现 $N$ 次 ## 样例解释 1 例如如下分配方式可以使 $\sum_j (c_j-a_j)$ 的值最小,为 $18$: - 第 $1$ 个人分到编号为 $1,5,9$ 的球。 - 第 $2$ 个人分到编号为 $2,4,8$ 的球。 - 第 $3$ 个人分到编号为 $3,6,7$ 的球。 由 ChatGPT 4.1 翻译 代码 #include<bits/stdc++.h> #define int long long // https://atcoder.jp/contests/agc037/tasks/agc037_b // http://goj.wiki/d/junior/p/1604 // https://www.luogu.com.cn/problem/AT_agc037_b using namespace std; const int MOD = 998244353; int N; string str; int R, G, B, RG, RB, GB, ans = 1; signed main(){ cin >> N; cin >> str; str = ’ ’ + str; for( int i = 1; i <= N * 3; i ++ ){ if( str[i] == ‘R’ ){ if( GB ) ans = ( ans * GB ) % MOD, GB --; else if( G ) ans = ( ans * G ) % MOD, RG ++, G --; else if( B ) ans *= B, RB ++, B --; else R ++; } else if( str[i] == ‘G’ ){ if( RB ) ans *= RB, RB --; else if( R ) ans *= R, RG ++, R --; else if( B ) ans *= B, GB ++, B --; else G ++; } else if( str[i] == ‘B’ ){ if( RG ) ans *= RG, RG --; else if( R ) ans *= R, RB ++, R --; else if( G ) ans *= G, GB ++, G --; else B ++; } ans %= MOD; } for( int i = 1; i <= N; i ++ ){ ans = ( ans * i ) % MOD; } cout << ans; return 0; }
10-09
再次调试,全WA#include<bits/stdc++.h> using namespace std; /* link: http://goj.wiki/d/junior/p/P1700 https://www.luogu.com.cn/problem/P6088 可持久化trie 建图 -> 将每条边的字符串丢到trie中,并且利用可持久化建出不同路径的版本。 然后计算答案的时候用到lca去减掉算多的 */ const int MAXN = 1e5 + 5; int N, Q; struct star{ int nxt, to; string str; }edge[MAXN * 2]; int head[MAXN], ccnt; void add( int u, int v, string & s ){ edge[++ ccnt] = { head[u], v, s }; head[u] = ccnt; } //---------------------------------------------- const int MAXM = 1300000; int tr[MAXM][30];//点p的字母c子节点 int cnt[MAXM], tot;//cnt[p]表示经过p的字符串数量 void insert( int pre, int now, string & s ){ int pree = pre, noww = now; for( int i = 0; i < s.size(); i ++ ){ int k = s[i] - ‘a’; for( int j = 0; j < 26; j ++ ){ if( j != k ) tr[noww][j] = ( pree ? tr[pree][j] : 0 ); } tr[noww][k] = ++ tot; noww = tr[noww][k]; pree = ( pree ? tr[pree][k] : 0 ); cnt[noww] = ( pree ? cnt[pree] : 0 ) + 1; } } int query( int root, string s ){//以 s 为前缀的字符串数量 int now = root; for( int i = 0; i < s.size(); i ++ ){ int k = s[i] - ‘a’; if( !tr[now][k] ) return 0;//不存在当前前缀 now = tr[now][k]; } return cnt[now]; } //---------------------------------------------------------------- int dep[MAXN], f[MAXN][21], root[MAXN]; //(from Qwen-Max) root[u]:表示从树的根节点(1)到节点 u 的路径上,所有边字符串插入后形成的 Trie 的根节点编号。 void dfs( int u, int fa ){ dep[u] = dep[fa] + 1; f[u][0] = fa; for( int i = 1; i <= 20; i ++ ){ f[u][i] = f[f[i - 1][u]][i - 1];//预处理倍增 } for( int i = head[u]; i; i = edge[i].nxt ){ int to = edge[i].to; if( to == fa ) continue; root[to] = ++ tot; insert( root[u], root[to], edge[i].str ); dfs( to, u ); } } int lca( int u, int v ){ if( dep[u] < dep[v] ) swap( u, v ); for( int i = 20; i >= 0; i – ){ if( dep[f[u][i]] >= dep[v] ) u = f[u][i]; } if( u == v ) return u; for( int i = 20; i >= 0; i – ){ if( f[u][i] != f[v][i] ){ u = f[u][i]; v = f[v][i]; } } return f[0][u]; } int main(){ // freopen( “data.in”, “r”, stdin ); freopen( “trie.in”, “r”, stdin ); freopen( “trie.out”, “w”, stdout ); cin >> N; for( int i = 1; i < N; i ++ ){ int u, v; string str; cin >> u >> v >> str; add( u, v, str ); add( v, u, str ); } dep[0] = -1; dfs( 1, 0 );//预处理 + 建trie cin >> Q; while( Q – ){ int u, v; string qb; cin >> u >> v >> qb; int p = lca( u, v ); cout << query( root[u], qb ) + query( root[v], qb ) - 2 * query( root[p], qb ) << endl; } return 0; }
10-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值