[C++/C] 繰り返し処理

### for文

int main() {
    
    for(int i=1; i<=5; i++) {
        cout << i << "番目の繰り返しです。\n";
    }

    cout << "繰り返しが終わりました。\n";

    return 0; 
}

入力した合計値出力

int main() {
    
    int num;
    int sum = 0;

    cout << "幾つまでの合計を求めますか。\n";

    cin >> num;

    for(int i=1; i<=num; i++) {
        sum += i;
    }

    cout << "1から" << num << "までの合計値は" << sum << "です。\n";

    return 0; 
}

### while文

int main() {
    
    int i = 1;

    while(i <= 5) {
        cout << i << "番目の繰り返しです。\n";
        i++;
    }

    cout << "繰り返しが終わりました。\n";

    return 0; 
}

i++を忘れると無限ループになる。

int main() {
    
    int num = 1;

    while(num) {
        cout << "整数を入力してください。(0で終了)\n";
        cin >> num;
        cout << num << "が入力されました。\n";
    }

    cout << "繰り返しが終わりました。\n";

    return 0; 
}

while(num) はwhile(num != 0)と同義

do ~ while

int main() {
    
    int i = 1;

    do {
        cout << i << "番目の繰り返しです。\n";
        i++;
    }
    while(i <= 5);

    cout << "繰り返しが終わりました。\n";

    return 0; 
}

### 文のネスト

int main() {
    
    for(int i = 0; i < 5; i++) {
        for(int j=0; j<3; j++) {
            cout << "iは" << i << ":jは" << j << "\n";
        }
    }

    return 0; 
}

if文と組み合わせ

int main() {
    
    int ch = 0;
    for(int i = 0; i < 5; i++) {
        for(int j=0; j<5; j++) {
            if (ch == 0) {
                cout << '*';
                ch = 1;
            } else {
                cout << '-';
                ch = 0;
            }
        }
        cout << "\n";
    }

    return 0; 
}

break

#include <iostream>
using namespace std;

int main() {
    
    int res;
    cout << "何番目でループを中止しますか?\n";
    cin >> res;

    for(int i = 0; i < 10; i++) {
        cout << i << "番目の処理です。\n";
        if (i == res)
            break;
    }

    return 0; 
}

continue

int main() {
    
    int res;

    cout << "何番目の処理を飛ばしますか。(1~10)\n";

    cin >> res;

    for(int i =1; i <= 10; i++) {
        if(i == res)
            continue;
        cout <<  i << "番目の処理です。\n";
    }

    return 0; 
}

### Practice

#include <iostream>
using namespace std;

int main() {
    
    cout << "1~10までの偶数を出力します。\n";

    for(int i =1; i <= 10; i++) {
        if(i % 2 == 0)
            cout <<  i << "\n"; 
    }

    return 0; 
}
int main() {
    
    int num, sum;
    num = 1;
    sum = 0;
    cout << "テストの点数を入力してください。(0で終了)\n";

    while(num){
        cin >>  num;
        sum += num; 
    }

    cout << "テストの合計点は" << sum << "点です。\n";

    return 0; 
}
int main() {
    
   for(int i=1; i<6; i++) {
        for(int j=0; j<i; j++){
            cout << "*";
        }
        cout << "\n";
   }

    return 0; 
}

入れ子の場合でも、iを使用してfor文を回すことで、
for(int j=1; j<6; j++) で入れ子にすると、以下のようになってしまう。 ***** ***** ***** ***** *****

[C++/C] 条件式

### if文

int main() {
    
    int res;

    cout << "整数を入力してください。\n";

    cin >> res;

    if(res == 1)
        cout << "1が入力されました。\n";;

    cout << "処理を終了します。\n";

    return 0; 
}

if else

int main() {
    
    int res;

    cout << "整数を入力してください。\n";
    cin >> res;

    if(res == 1) {
        cout << "1が入力されました。\n";
    } else {
        cout << "1以外が入力されました。\n";
    }
    
    cout << "処理を終了します。\n";

    return 0; 
}

else if

int main() {
    
    int res;

    cout << "整数を入力してください。\n";
    cin >> res;

    if(res == 1) {
        cout << "1が入力されました。\n";
    } else if(res == 2) {
        cout << "2が入力されました。\n";
    } else {
        cout << "1か2を入力してください。\n";
    }
    
    cout << "処理を終了します。\n";

    return 0; 
}

### switch文

int main() {
    
    int res;

    cout << "整数を入力してください。\n";
    cin >> res;

    switch(res) {
        case 1:
            cout << "1が入力されました。\n";
            break;
        case 2:
            cout << "2が入力されました。\n";
            break;
        default:
            cout << "1か2を入力してください。\n";
            break;
    }

    return 0; 
}

### 複雑な条件判断

int main() {
    
    char res;

    cout << "あなたは男性ですか?\n";
    cout << "YかNを入力してください。\n";

    cin >> res;

    if (res == 'Y' || res == 'y') {
        cout << "あなたは男性ですね。\n";
    } else if (res == 'N' || res == 'n') {
        cout << "あなたは女性ですね。\n";
    } else {
        cout << "YかNを入力してください。\n";
    }

    return 0; 
}

### 条件演算子

int main() {
    
    int res;
    char ans;

    cout << "何番目のコースにしますか?\n";
    cout << "整数を入力してください。\n";

    cin >> res;

    if (res == 1)
        ans = 'A';
    else
        ans = 'B';

    cout << ans << "コースを選択しました。\n";

    return 0; 
}
int main() {
    
    int res;
    char ans;

    cout << "何番目のコースにしますか?\n";
    cout << "整数を入力してください。\n";

    cin >> res;

    ans = (res == 1) ? 'A' : 'B';

    cout << ans << "コースを選択しました。\n";

    return 0; 
}

ans = (res == 1) ? ‘A’ : ‘B’; の書き方

### practice

int main() {
    
    int num;

    cout << "整数を入力してください。\n";

    cin >> num;

    if (num % 2 == 0) {
        cout << num << "は偶数です。\n";
    } else if(num % 2 == 1) {
        cout << num << "は奇数です。\n";
    } else {
        cout << "整数を入力してください。\n";
    }

    return 0; 
}
#include <iostream>
using namespace std;

int main() {
    
    int num1, num2;

    cout << "2つの整数を入力してください。\n";

    cin >> num1;
    cin >> num2;

    if (num1 == num2) {
        cout << "2つの数は同じ値です。\n";
    } else if(num1 > num2) {
        cout << num2 << "より" << num1 << "の方が大きい値です。\n";
    } else {
        cout << num1 << "より" << num2 << "の方が大きい値です。\n";
    }

    return 0; 
}
int main() {
    
    int result;

    cout << "成績を入力してください。\n";

    cin >> result;

    switch(result){
        case 1:
            cout << "成績は1です。もっと頑張りましょう。\n";
            break;
        case 2:
            cout << "成績は2です。もう少し頑張りましょう。\n";
            break;
        case 3:
            cout << "成績は3です。さらに上を目指しましょう。\n";
            break;
        case 4:
            cout << "成績は4です。大変良くできました。\n";
            break;
        case 5:
            cout << "成績は5です。大変優秀です。\n";
            break;
        default:
            cout << "成績を入力してください。\n";
            break;
    }

    return 0; 
}

if(res % 2)は 0でなければ奇数と判断される
cin >> num1 >> num2とも書ける

bitcoinのブロック

### ブロックの構造と識別子
Block Size: 4bytes
Block Header: 80
Transaction Counter: 1~9 (ブロックに含まれているトランザクション数)
Transactions: 可変(トランザクションのリスト)

### ブロックヘッダの構造
Version: 4bytes
Previous Block Hash: 32
Merkle Root: 32
Timestamp: 4
Difficulty Target: 4
Nonce: 4

ブロックヘッダだけ保持するノードをSPV(Simplified Payment Verification)ノードという
ブルームフィルタとは、「このトランザクションを確認できるマークルパスをrequest」という要求を粗い要求に転換することで、どのトランザクションに関心があるかを特定しにくくするもの(BIP0037)

### 通常のトランザクションとcoinbaseトランザクション
通常のトランザクション
Transaction Hash: 32bytes
Output Index: 4
Unlockking Script Size: 1~9
Unlocking Script: 可変

coinbaseトランザクション
Transaction Hash: 32(他のトランザクションを参照しないため、全てのビットが「0」固定)
Output Index: 4 全てのビットが1固定
Coinbase Data Size: 1~9 (coinbase data sizeは2~100bytes)
Coinbase Data: 可変 (Extra NonceやMining Tagに使われる)
Sequence Number: 4(0x00000000)

### Segregated Witness
Segregated Witnessはトランザクションの署名をトランザクションインプットから切り離し別の領域に移す仕様で、2017年8月にアクティベートされた
サイズの大きい署名部分をトランザクションから切り離してwitnessに格納する
Lightning Netowrokとは、最初のトランザクションと最後のトランザクションのみをビットコインネットワークのブロックに記録して、その間のトランザクションはライトニングネットワーク内でのみ記録する

– SegWitのトランザクションの構造
Version no: 4bytes
Marker: 1 ★追加
Flag: 1
Input Counter: 1~9 (インプットの数)
Inputのリスト: 可変
Output Counter: 1~9 (アウトプットの数)
Outputのリスト: 可変
Script Witness: 可変 (witnessの要素の数とwitnessが設定される)
Locktime:4

### ブロックサイズの計算方法
block wight = ベースサイズ(全トランザクションのバイト数) * 3 + トータルサイズ(witnessを含むSegwit構造での全トランザクションバイト数)

P2WPKHでは
Locking Script: OP_0

[C++/C] 演算子の種類2

sizeof演算子

int main() {
    
    int a = 1;
    int b = 0;

    cout << "short int型のサイズは" << sizeof(short int) << "バイトです。\n";
    cout << "int型のサイズは" << sizeof(int) << "バイトです。\n";
    cout << "long int型のサイズは" << sizeof(long int) << "バイトです。\n";
    cout << "float型のサイズは" << sizeof(float) << "バイトです。\n";
    cout << "double型のサイズは" << sizeof(double) << "バイトです。\n";
    cout << "long double型のサイズは" << sizeof(long double) << "バイトです。\n";
    cout << "変数aのサイズは" << sizeof(a) << "バイトです。\n";
    cout << "式a+bのサイズは" << sizeof(a+b) << "バイトです。\n";
    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
short int型のサイズは2バイトです。
int型のサイズは4バイトです。
long int型のサイズは8バイトです。
float型のサイズは4バイトです。
double型のサイズは8バイトです。
long double型のサイズは16バイトです。
変数aのサイズは4バイトです。
式a+bのサイズは4バイトです。

### シフト演算子
数値を2進数で表した場合の桁を左または右に指定数だけずらす演算です。

### 型変換

int main() {
    
    int inum = 160;
    double dnum;

    cout << "身長は" << inum << "センチです。\n";
    cout << "double型の変数に代入します。\n";

    dnum = inum;

    cout << "身長は" << dnum << "センチです。\n";
    return 0; 
}
int main() {
    
    double dnum = 160.5;
    int inum;

    cout << "身長は" << dnum << "センチです。\n";
    cout << "int型の変数に代入します。\n";

    inum = dnum;

    cout << "身長は" << inum << "センチです。\n";
    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
身長は160.5センチです。
int型の変数に代入します。
身長は160センチです。

### キャスト演算子
型を変換することを明示する
dnum = (double)inum;

### 異なる型同士で演算する

int main() {
    
    int d = 2;
    const double pi = 3.14;

    cout << "直径が" << d << "センチの円の\n";
    cout << "円周は" << d*pi << "センチです。\n";

    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
直径が2センチの円の
円周は6.28センチです。

double とintをかけると doubleになる。

### 同じ型同士の演算

int main() {
    
    int num1 = 5;
    int num2 = 4;
    double div;

    div = num1 / num2;

    cout << "5/4は" << div << "です。\n";

    return 0; 
}

int と intの計算のため、回答は1で出力される。(double)num1/(double)num2とキャストした場合は1.25で出力される。

### practice

int main() {
    

    cout << "0-4は" << 0-4 << "です。\n";
    cout << "3.14x2は" << 3.14*2 << "です。\n";
    cout << "5/3は" << 5/3 << "です。\n";
    cout << "30/7の余りは" << 30%7 << "です。\n";
    cout << "(7*32)/5は" << (7*32)/5 << "です。\n";

    return 0; 
}

三角形の面積

int main() {
    
    double height, base;

    cout << "三角形の高さを入力してください。\n";
    cin >> height;

    cout << "三角形の底辺を入力してください。\n";
    cin >> base;

    cout << "三角形の面積は" << height*base/2 << "です。\n";

    return 0; 
}

$ g++ -o sample sample.cpp && ./sample
三角形の高さを入力してください。
3
三角形の底辺を入力してください。
5
三角形の面積は7.5です。

#include <iostream>
using namespace std;

int main() {
    
    int num1, num2, num3, num4, num5;

    cout << "科目1の点数を入力してください。\n";
    cin >> num1;

    cout << "科目2の点数を入力してください。\n";
    cin >> num2;

    cout << "科目3の点数を入力してください。\n";
    cin >> num3;

    cout << "科目4の点数を入力してください。\n";
    cin >> num4;

    cout << "科目5の点数を入力してください。\n";
    cin >> num5;

    cout << "5科目の合計点は" << num1+num2+num3+num3+num4+num5 << "です。\n";
    cout << "5科目の平均点は" << (num1+num2+num3+num3+num4+num5)/5 << "です。\n";

    return 0; 
}

合計値の場合は、int sum=0, num=0と宣言した上で、
cin >> num;
sum += num;とする方がスマート

[C++/C]式と演算子

int main() {
    
    cout << "1+2=" << 1+2 << "です。\n"; 
    cout << "3+4=" << 3*4 << "です。\n";
    return 0; 
}
int main() {
    
    int num1, num2;

    cout << "整数1を入力してください。\n";
    cin >> num1;

    cout << "整数2を入力してください。\n";
    cin >> num2;

    cout << "結果は" << num1 + num2 << "です。\n";
    return 0; 
}

演算子の種類
+, -, *, /, %, +, -, ~, &, |, ^, <<, >>, ++, –, >, >=, < 前後のインクレメント b = ++a; は代入前なので1となる。 代入演算子のバリエーション +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=

int main() {
    
    int sum = 0;
    int num = 0;

    cout << "1番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "2番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "3番目の整数を入力してください。\n";
    cin >> num;
    sum += num;

    cout << "合計値は" << sum << "です。\n";
    return 0; 
}

SRM150 InterestingDigits

The digits 3 and 9 share an interesting property. If you take any multiple of 3 and sum its digits, you get another multiple of 3. For example, 118*3 = 354 and 3+5+4 = 12, which is a multiple of 3. Similarly, if you take any multiple of 9 and sum its digits, you get another multiple of 9. For example, 75*9 = 675 and 6+7+5 = 18, which is a multiple of 9. Call any digit for which this property holds interesting, except for 0 and 1, for which the property holds trivially.

A digit that is interesting in one base is not necessarily interesting in another base. For example, 3 is interesting in base 10 but uninteresting in base 5. Given an int base, your task is to return all the interesting digits for that base in increasing order. To determine whether a particular digit is interesting or not, you need not consider all multiples of the digit. You can be certain that, if the property holds for all multiples of the digit with fewer than four digits, then it also holds for multiples with more digits. For example, in base 10, you would not need to consider any multiples greater than 999.

#include <vector>
using namespace std;

class InterestingDigits {
    public:
        vector <int> digists(int base) {
            vector <int> ans;

            for(int n=2; n<base; n++) {
                bool ok = true;
                for(int k1=0; k1<base; k++) {
                    for(int k2=0; k2<base; k2++) {
                        (for int k3=0; k3<base; k3++) {
                            if((k1 + k2*base + k3*base*base) % n == 0
                                &&(k1 + k2 + 3)%n != 0){
                                    ok = false;
                                    break;
                                }
                        }
                        if (!ok) break;
                    }
                    if(!ok) break;
                }
                if(ok) ans.push_back(n);
            }
            return ans;
        }
}

対象の答えがあったときは配列にappendしていく。
桁数が複数あるときは、*base, *base*base と表現する。

n真数で表した1と10が、baseで割った余りと等しければ、どの桁もbaseで割った余りが等しいことが証明可能となる

#include <vector>
using namespace std;

class InterestingDigits {
    public:
        vector <int> digits(int base){
            vector <int> ans;

            for (int i=2; i<base; i++) {
                if (((base - 1) % 1) == 0) ans.push_back(i);
            }
        }
}

数学知識があると大分違うようです。

[bitcoin基礎技術] ECDSA署名と検証

m: 署名対象のメッセージ
Q = dG : Q公開鍵、dは秘密鍵、Gはsecp256k1ベースポイント
n: secp256k1の位数

### ECDSA署名の生成
1. ハッシュ関数にメッセージmを渡し、ハッシュ値m’を取得する(m’=H(m))
2. [1, n-1]の範囲からkを選択し、楕円曲線上の点Rを k*Gで求める (R = kG)
3. R= rx, ry とする。Rのx座標rxを位数nで割った余剰を求める r = rx mod n
4. s = (m'(ハッシュしたメッセージ) + d(秘密鍵)*r(Rのx座標)) / k(任意の点) mod n
5. (r, s)が m に対する署名となる

### ECDSA署名の検証
1. P = (px, py)とする
P = m’/s * G + r / s * Q (公開鍵)(mod n)
この時、Px = r(mod n) となるとき、署名検証に成功

パラメータkを生成
$ openssl ecparam -genkey -name secp256k1 -out k.pem; ls k.pem
$ openssl ec -in k.pem -outform DER | tail -c +8 | head -c 32 | xxd -p -c 32
read EC key
writing EC key
a891fce013c907a3ce5e157d1edc474bbdf7efc0c133b41cad14aca3566c914c
$ k=a891fce013c907a3ce5e157d1edc474bbdf7efc0c133b41cad14aca3566c914c

Rを生成
$ openssl ec -in k.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65
read EC key
writing EC key
042ce7c2a48e71ad11e4445b3901d4afe715c0298ed1504cb4ce47b426d83bfaa7bb4665d4c92b9484c4b0ce5cfcabe089e1e2a7c8e32a3c6b5f2d2c0ba301fb97
$ R=042ce7c2a48e71ad11e4445b3901d4afe715c0298ed1504cb4ce47b426d83bfaa7bb4665d4c92b9484c4b0ce5cfcabe089e1e2a7c8e32a3c6b5f2d2c0ba301fb97

Rからrxを取り出し、変数rxに格納
$ rx=`echo $R | cut -c3-66`; echo $rx
2ce7c2a48e71ad11e4445b3901d4afe715c0298ed1504cb4ce47b426d83bfaa7

メッセージのハッシュ値を生成し、変数mhに格納
$ mh=`cat message.txt | xxd -r -p | openssl dgst -sha256 | cut -c10-`; echo $mh
stdin)= 45f83d17e10b34fca01eb8f4454dac34a777d9404a464e732cf4abf2c0da94c4

公開鍵をQに格納
$ Q=$pubKey; echo $Q
047a2b8a7974ed6f4b7817b0f354c6c81ceacb210e53e093eadcd4d4ece0bb4d60a0864e802eb58b813183cd4bae108588e062ec61e6bff36f68ad530ee11cff15

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def multiply_inv(a, m):
    if a < 0:
        a = a % m
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('multiply modular inverse does not exist')
    else:
        return x % m

[C++/C] 型, 変数, キーボードからの入力, 定数

基本型
bool, char, unsigned char(符号なし), short int, unsigned short int, int, unsigned int, long int, unsigned long int, float, double, long double

bitとbytes
2進数の1桁分をbitと呼ぶ
00101110

2進数の8桁の数値はbyteと呼ぶ

### 変数の利用

#include <iostream>
using namespace std;

int main() {
    int num;
    num = 3;

    cout << "変数numの値は" << num << "です。\n";

    return 0;
}

変数の値を変更

int main() {
    int num = 3;
    cout << "変数numの値は" << num << "です。\n";

    num = 5;

    cout << "新しい変数numの値は" << num << "です。\n";

    return 0;
}

他の変数の値を代入

int main() {
    int num1, num2;
    num1 = 3;

    cout << "変数num1の値は" << num1 << "です。\n";

    num2 = num1;

    cout << "変数num2の値は" << num2 << "です。\n";

    return 0;
}

値の代入と型変換

int main() {
    int num1;
    double num2;

    num1 = 3.14;
    num2 = 3.14;

    cout << "変数num1の値は" << num1 << "です。\n";
    cout << "変数num2の値は" << num2 << "です。\n";

    return 0;
}

$ g++ -o sample sample.cpp && ./sample
変数num1の値は3です。
変数num2の値は3.14です。
// 小数点以下は切り捨てられる

キーボードからの入力
=> cin >> 変数; と記載する

int main() {
    int num = 0;

    cout << "整数を入力してください。\n";

    cin >> num;

    cout << num << "が入力されました。\n";

    return 0;
}

2つ以上の数値の入力

int main() {
    int num1, num2;

    cout << "整数を2つ入力してください。\n";

    cin >> num1 >> num2;

    cout << "最初に" << num1 << "が入力されました。\n";
    cout << "次に" << num2 << "が入力されました。\n";

    return 0;
}

定数はconstを指定する
初期化によって変数を変更できないようにする

int main() {
    const double pi = 3.1415;

    cout << "円周率の値は" << pi << "です。\n";

    return 0;
}

practice 1

int main() {
    double pi;

    cout << "円周率の値は幾つですか?\n";

    cin >> pi;

    cout << "円周率の値は" << pi << "です。\n";

    return 0;
}

practice 2

int main() {
    char str;

    cout << "アルファベットの最初の文字は何ですか?\n";

    cin >> str;

    cout << "アルファベットの最初の文字は" << str << "です。\n";

    return 0;
}

practice 3

int main() {
    double height, weight;

    cout << "身長と体重を入力してください。\n";

    cin >> height >> weight;

    cout << "身長は" << height << "です。\n";
    cout << "体重は" << weight << "です。\n";

    return 0;
}

c++では文字列の変数名はstrよりもchの方が型との違いがなく表現としては望ましそうです。

SRM 480 Cryptography

Problem Statement TopCoder Security Agency (TSA, established today) has just invented a new encryption system! This encryption system takes as its input a list of numbers to encrypt. You work at TSA and your task is to implement a very important part of the encryption process. You are allowed to pick one number in the input list and increment its value by 1. This should be done in such way that the product of all numbers in the list after this change becomes as large as possible. Given the list of numbers as vector numbers, return the maximum product you can obtain. It is guaranteed that the return value will not exceed 2^62. Definition Class: Cryptography Method:encrypt Parameters:vector Returns:long long Method signature:long long encrypt(vector numbers) (be sure your method is public) Constraints – numbers will contain between 2 and 50 elements, inclusive. – Each element of numbers will be between 1 and 1000, inclusive. – The return value will not exceed 2^62. Examples 0) {1,2,3} Returns: 12 If we increment the first number, we get 2*2*3 = 12. If we increment the second, we get 1*3*3 = 9. If we increment the third, we get 1*2*4 = 8. Hence, the correct return value is 12. 1) {1,3,2,1,1,3} Returns: 36 The elements of numbers are not necessarily unique. 2) {1000,999,998,997,996,995} Returns: 986074810223904000 The answer may be very big, but will not exceed 2^62. 3) {1,1,1,1} Returns: 2 This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited.

#include <vector>
using namespace std;

class Cryptography {
    public:
        long long encrypt(vector <int> numbers) {
            long long ans = 0;

            for(int i=0; i<numbers.size(); i++) {
                long long seki=1;
                for (int j=0; j<numbers.length; j++){
                    if (i==j) {
                        seki *= (numbers[j] + 1);
                    } else {
                        seki *= numbers[j];
                    }
                }
                ans = max(ans, seki);
            }
            return ans;
        }
}

この問題は小さい数字に1を足す。その場合、増加率が最も大きくなる。

#include <vector>
#include <algorithm>
using namespace std;

class Cryptography {
    public:
        long long encrypt(vector <int> numbers) {
            long long ret = 1;
            sort(numbers.bigin(), numbers.end());
            numbers[0]++;

            for (int i = 0; i < number.size(); i++){
                ret *= numbers[i];
            }
            return ret;
        }
}

[C++/C] ポインタ

ポインタは変数のアドレスを持つ変数のこと
変数のアドレス場所を表すには、変数の頭に&をつける

ポインタ型とは、変数のアドレスを保存しておくための型
下記は同じ意味

char* test;
char *test;
#include <stdio.h>

int main(void) {

    char buf[50] = "bitcoin";
    char *test;

    test = buf;
    printf("%s", test);
    return 0;
}

文字列の後ろにつけるアスタリスクがあるのかと勘違いしてしまいますね。