using System;
using System.Collections;
namespace ConsoleApp
{
class Program
{
public static void Main(string[] args)
{
int? a = null;
Console.WriteLine("a의 값 {0}", a);
float? b = null;
Console.WriteLine("b의 값 {0}", b);
ArrayList arraylist = null;
arraylist?.Add(30); //arraylist가 null이 아니면 Add(30)
/*
if (arraylist == null)
{
arraylist.Add(30);
}
*/
Console.WriteLine(arraylist?[0]); //null 이지만 오류가 나지 않습니다.
a = a ?? 20; //a가 null이면 20
b = b ?? 30.9f; //b가 null 이면 30.9f
Console.WriteLine("a = {0}, b = {1}", a, b);
}
}
}
using System;
using System.IO; //...Stream
namespace ConsoleApp
{
class Program
{
public static void Main(string[] args)
{
//바이너리 파일 생성 및 저장
FileStream fs = new FileStream("Test.bin", FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
string input1 = Console.ReadLine();
int input2 = Convert.ToInt32(Console.ReadLine());
float input3 = Convert.ToSingle(Console.ReadLine());
bw.Write(input1); //string
bw.Write(input2); //int
bw.Write(input3); //float
bw.Close();
fs.Close();
//바이너리 파일 읽어오기
FileStream fs2 = new FileStream("Test.bin", FileMode.Open);
BinaryReader br = new BinaryReader(fs2);
Console.WriteLine(br.ReadString()); //string
Console.WriteLine(br.ReadInt32()); //int
Console.WriteLine(br.ReadSingle()); //float
br.Close();
fs2.Close();
}
}
}
입력을 받고 읽어온 모습저장된 데이터
2. StreamReader/StreamWriter 를 이용한 모습입니다. 문자열 그대로 저장이 됩니다.
using System;
using System.IO; //...Stream
namespace ConsoleApp
{
class Program
{
public static void Main(string[] args)
{
StreamWriter sw = new StreamWriter("Test.dat");
for (int i = 0; i < 5; ++i) //5개의 입력
{
sw.WriteLine(Console.ReadLine());
}
sw.Close();
StreamReader sr = new StreamReader("Test.dat");
while (!sr.EndOfStream) //sr.ReadLine() == null인 경우입니다.
{
Console.WriteLine(sr.ReadLine());
}
sr.Close();
}
}
}
(이분 탐색이 left <= right, left < right 등과 같이 여러 변형이 있고 쓰이는 곳이 달라집니다.
이건 종이에 써가면서 해보는게 좋을거 같네요!)
#include <iostream>
#include <algorithm>
using namespace std;
int input[1000000];
int BinarySearch(int n, int m)
{
int left = 0;
int right = 1000000000;
while (left <= right)
{
int mid = (left + right) / 2;
long long sum = 0LL;
for (int i = 0; i < n; ++i)
{
if (input[i] > mid)
{
sum += (long long)input[i] - (long long)mid;
}
}
if (sum == m)
{
return mid;
}
else if (sum > m)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return right;
}
int main()
{
int n, m;
int left = 0;
int right = 0;
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < n; ++i)
{
cin >> input[i];
}
sort(input, input + n);
cout << BinarySearch(n, m) << endl;
}
다른 방법은 높이를 큰 순서로 나열한 후 잘라가며 원하는 수량을 체크하는 것입니다.
이 방법은 제가 알아낸 것은 아니고 어떤 분의 풀이였던 것 같습니다.
1
2
#include <iostream>
#include <algorithm>
using namespace std;
int input[1000001];
bool compare(int a, int b)
{
return a > b;
}
int main()
{
int n, m;
long long sum = 0;
int index = 1;
int cut = 0;
cin >> n >> m;
for (int i = 0; i < n; ++i)
{
cin >> input[i];
}
sort(input, input + n, compare);
while (sum < m)
{
sum += ( (long long)input[index - 1] - (long long)input[index] ) * index;
index++;
}
cut = (sum - m) / (index - 1);
cout << input[index - 1] + cut << endl;
}
cut을 구하는 것이 핵심인 코드입니다. ㅎㅎ
(이때 index가 배열의 크기를 넘어서지 않기위해 n + 1개 만큼의 배열로 선언해주어야 합니당.)
using UnityEngine;
[CreateAssetMenu(fileName = "MyEditorData", menuName = "Custom ScriptableObject/MyEditorData")]
public class MyEditorData : ScriptableObject
{
public string filePath;
}
우선 string형 하나만 입력받도록 설정해줍니다. 클래스는 ScriptableObject 를 상속 받기만 하면 됩니다.
4. eulerPhi 보다 작고 eulerPhi와 서로소인 정수 e를 찾아 선택합니다. (e가 공개키가 됩니다.)
5. d * e % eulerPhi == 1 인 d를 찾습니다. (d가 개인키가 됩니다.)
6. 최종적으로 키가 생성됩니다.
<e, n> 공개키, <d, n> 개인키
암호화 방법
메시지를 e번 제곱해주고 n으로 나눈 나머지를 얻습니다.
복호화 방법
메시지를 d번 제곱해주고 n으로 나눈 나머지를 얻습니다.
주의사항) n은 우리가 사용하는 문자 값보다 커야됩니다.
n이 'A' (65) 보다 작다면 A라는 의미를 잃어버리기 때문입니다.
프로그램에선 숫자가 너무 커지므로 제곱할 때마다 n으로 나눠주고 있습니다.
코드가 좀 길어서 제가 다시 볼지 모르겠습니다 ㅋㅋ;
코드 흐름
1. InitPrime() : 에라토스테네스의 체를 통해 notPrime배열에 소수를 구해두기
2. 소수 p, q를 입력받기
3. 오일러피 값을 구합니다. eulerPhi = (p - 1) * (q - 1)
4. GetRelativePrime() : eulerPhi 에 서로수인 숫자를 구합니다. (최대공약수를 찾기 위해 GCD 가 쓰입니다)
5. 공개키 e 입력 받기
6. FindPrivateDKey() : 개인키 후보를 찾습니다.
7. 개인키 d 입력 받기
8. 문자열 입력
9. Encryption() : 암호화 및 출력
(여기서 char 배열에서 int 배열로 바꿔서 저장합니다.
char는 1byte (=8bit) 최대 255까지밖에 표현되지 않아 값을 잃어버리기 때문입니다.)
10. Decryption() : 암호를 복호화하여 출력
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MaxSize = 10000;
const int Size = 100;
const int LineLength = 14;
bool notPrime[MaxSize];
bool relativePrime[MaxSize]; //서로소
char input[100];
int encryptToInt[100];
vector<long long> dList;
void InitPrime()
{
notPrime[0] = notPrime[1] = true;
for (int i = 2; i * i <= MaxSize; ++i)
{
if (notPrime[i])
{
continue;
}
for (int j = i * i; j <= MaxSize; j += i)
{
notPrime[j] = true;
}
}
}
void PrintPrime(int enterLine, int size)
{
printf("====소수 목록====\n");
int line = 0;
for (int i = 2; i < Size; ++i)
{
if (notPrime[i])
{
continue;
}
printf("%3d ", i);
line++;
if (line >= enterLine)
{
line = 0;
printf("\n");
}
}
}
int GCD(int a, int b) //Greatest Common Divisor 최대 공약수 찾기
{
while (b != 0)
{
int c = a % b;
a = b;
b = c;
}
return a;
}
void GetRelativePrime(int enterLine, int phi)
{
int line = 0;
for (int i = 1; i < phi; ++i)
{
if (GCD(i, phi) == 1)
{
line++;
printf("%3d ", i);
relativePrime[i] = true;
if (line >= enterLine)
{
line = 0;
printf("\n");
}
}
}
}
void FindPrivateDKey(int e, int eulerPhi, int many)
{
for (long long d = 1; dList.size() < many; ++d)
{
if (d * e % eulerPhi == 1)
{
dList.push_back(d);
printf("[%d]번째 가능한 개인키 d = %lld [ %lld * %d %% %d = 1 ]\n", dList.size(), d, d, e, eulerPhi);
}
}
}
int Pow(int value, int e, int n)
{
int v = value;
for (int i = 1; i < e; ++i)
{
v = v * value % n;
}
return v;
}
void Encryption(int e, int n)
{
char encryptForPrint[100] = { 0 };
int length = strlen(input);
for (int i = 0; i < length; ++i)
{
int value = Pow(input[i], e, n);
//char는 1바이트로 8bit, 최대 2^8 (256) 까지밖에 표현이 불가능하여
//값이 256을 넘으면 오버플로우 발생
encryptToInt[i] = value;
encryptForPrint[i] = value;
}
printf("%s\n", encryptForPrint);
}
void Decryption(int d, int n)
{
char decryptForPrint[100] = { 0 };
int length = strlen(input);
for (int i = 0; i < length; ++i)
{
decryptForPrint[i] = Pow(encryptToInt[i], d, n);
}
printf("%s\n", decryptForPrint);
}
int main()
{
int p, q, n, e;
long long d;
InitPrime();
PrintPrime(LineLength, Size);
printf("\n\n두 개의 소수를 입력하세요.\n");
while (true)
{
scanf("%d %d", &p, &q);
if (notPrime[p] || notPrime[q])
{
printf("\n소수를 다시 입력하세요.\n");
continue;
}
break;
}
n = p * q; //[중요] n보다 작은 값들에 대해서만 암호화가 가능하다!!! % n 으로 나누어주기 때문이다.
int eulerPhi = (p - 1) * (q - 1);
printf("\n오일러 피 함수 값 %d * %d = %d\n", (p - 1), (q - 1), eulerPhi);
printf("====%d와 서로수인 수====\n", eulerPhi);
GetRelativePrime(LineLength, eulerPhi);
printf("\n\n");
while (true)
{
scanf("%d", &e);
if (relativePrime[e])
{
break;
}
else
{
printf("\n서로수인 수를 입력해야됩니다.\n");
}
}
FindPrivateDKey(e, eulerPhi, 5); //5개를 구해보자
printf("\n개인키를 입력하세요.\n");
while (true)
{
scanf("%lld", &d);
bool isContain = false;
for (int i = 0; i < dList.size(); ++i)
{
if (dList[i] == d)
{
isContain = true;
break;
}
}
if (isContain)
{
break;
}
else
{
printf("\n올바른 개인키를 입력해야 됩니다.\n");
}
}
printf("\n\n 공개키 [e = %d, n = %d], 개인키 [d = %lld, n = %d]\n\n", e, n, d, n);
printf("100문자 이내로 평문을 작성해보세요.\n");
printf("(단 n의 크기가 해당 문자를 나타내는 숫자보다 작다면 변환값을 잃게 됩니다.)\n");
printf("ex) 'A' = 65, n = 42라면 65값을 잃게 됩니다.\n\n");
getchar(); //버퍼에 엔터키 제거용
gets_s(input);
printf("\n평문을 암호화 합니다.\n");
Encryption(e, n);
printf("\n==============================================\n");
printf("\n평문을 복호화 합니다.\n\n");
Decryption(d, n);
return 0;
}
#include <iostream>
using namespace std;
int GCD(int a, int b)
{
while (b != 0)
{
int c = a % b;
a = b;
b = c;
}
return a;
}
int main()
{
cout << GCD(21, 12);
}
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
clock_t start = clock(); //ms 단위를 반환 합니다. 1s == 1000ms
int i = 0;
int second = 0;
while (second < 5)
{
clock_t end = clock();
i++;
if (end - start >= 1000)
{
second++;
start = end;
cout << second << "초 경과 i 값은 " << i << endl;
}
}
}