技巧
切换编译器c++版本
-std=c++11
万能头
#include <bits/stdc++.h>
cin cout加速
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
全排列函数
next_permutation(a,a+n);
stl的优先队列
priority_queue<PII,vector<PII>,greater<PII>>
string的常用方法
string a;
cin>>a;
//字符串查找
if(a.find("yu",8)!=a.npos)
cout<<"Yes";
else
cout<<"No";
//字符串截取
cout<<a.substr(1,5);
//从下标从1的位置开始向后截取5个
getline(cin,s);
整行输入
//高精度加法
数组模拟版本
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 1e6 + 10, mod = 1e18;
int na[N], cnta;
int nb[N], cntb;
int f[N];
int n, t, s, m, x;
void add() {
for (int i = n; i >= 1; i--) {
na[i - 1] += (na[i] + nb[i]) / 10;
na[i] = (na[i] + nb[i]) % 10;
}
}
signed main() {
string a, b;
cin >> a >> b;
n = a.length();
m = b.length();
if (n < m) {
string t = a;
a = b;
b = t;
int tp = n;
n = m;
m = tp;
}
int tmp = abs(n - m);
for (int i = 0; i < n; i++) {
na[i + 1] = a[i] - '0';
}
for (int i = 0; i < m; i++) {
nb[i + 1 + tmp] = b[i] - '0';
}
add();
if (na[0] != 0) {
cout << na[0];
}
for (int i = 1; i <= n; i++) cout << na[i];
return 0;
}
vector版本
#include<iostream>
using namespace std;
#include<vector>
const int n=1e6+10;
vector<int >add(vector<int>&A,vector<int>&B)
{
vector<int>C;
int t=0;
for(int i=0;i<A.size()||i<B.size();i++)
{
if(i<A.size())t+=A[i];
if(i<B.size())t+=B[i];
C.push_back(t%10);
t/=10;
}
if(t)C.push_back(1);
return C;
}
int main()
{
string a,b;
vector<int >A,B;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i-- ) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i-- ) B.push_back(b[i]-'0');
auto C=add(A,B);
for(int i=C.size()-1;i>=0;i--){
printf("%d",C[i]);
}
return 0;
}
高精度减法
数组模拟
// Problem: 选数异或
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/4648/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> PII;
const int N = 1e6 + 10, mod = 1e18;
int na[N], cnta;
int nb[N], cntb;
int f[N];
int n, t, s, m, x;
void add() {
for (int i = n; i >= 1; i--) {
if (na[i] < nb[i]) {
na[i - 1] -= 1;
na[i] = na[i] + 10 - nb[i];
} else
na[i] = na[i] - nb[i];
}
}
signed main() {
string a, b;
cin >> a >> b;
n = a.length();
m = b.length();
int flag = 1;
if (n < m) {
flag = -1;
}
if (n < m) {
string t = a;
a = b;
b = t;
int tp = n;
n = m;
m = tp;
}
if (n == m) {
for (int i = 0; i < n; i++) {
if (a[i] > b[i])
break;
else if (a[i] < b[i]) {
flag = -1;
string t = a;
a = b;
b = t;
int tp = n;
n = m;
m = tp;
break;
}
}
}
int tmp = abs(n - m);
for (int i = 0; i < n; i++) {
na[i + 1] = a[i] - '0';
}
for (int i = 0; i < m; i++) {
nb[i + 1 + tmp] = b[i] - '0';
}
add();
if (flag < 0) cout << "-";
int i = 1;
while (na[i] == 0) i++;
for (; i <= n; i++) cout << na[i];
return 0;
}
vector模拟
#include <iostream>
using namespace std;
#include <vector>
bool cmp(vector<int>& A, vector<int>& B) {
if (A.size() != B.size()) return A.size() > B.size();
for (int i = A.size() - 1; i >= 0; i--)
if (A[i] != B[i]) return A[i] > B[i];
}
vector<int> sub(vector<int>& A, vector<int>& B) {
vector<int> C;
int t = 0;
for (int i = 0, t = 0; i < A.size(); i++) {
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0)
t = 1;
else
t = 0;
}
while (C.size() > 1 && C.back() == 0)
C.pop_back(); //去前导零,保证只剩一位时输出10
return C;
}
int main() {
string a, b;
vector<int> A, B;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
if (cmp(A, B)) {
auto C = sub(A, B);
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
} else {
auto C = sub(B, A);
printf("-");
for (int i = C.size() - 1; i >= 0; i--) printf("%d", C[i]);
}
return 0;
}
高精度乘低精度乘法
vector模拟版本
//自研版本
vector<int> add(vector<int> v, ll b) {
int tmp = 0;
for (int i = 0; i < v.size(); i++) {
int t = v[i] * b / 10;
v[i] = (v[i] * b + tmp) % 10;
tmp = t;
}
while (tmp) {
v.push_back(tmp % 10);
tmp /= 10;
}
return v;
}
//acwing版本
vector<int> mul(vector<int>& a, int b) {
vector<int> c;
int t = 0;
int n = a.size();
for (int i = 0; i < n || t; i++) {
if (i < n) t += a[i] * b;
c.push_back(t % 10);
t /= 10;
}
return c;
}
高精度乘高精度(数组模拟版本)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int, int> PII;
const int N = 1e5 + 10, mod = 1e9 + 7;
int x[N], y[N];
string a, b;
int c[N];
int len;
void mul() {
len = a.size() + b.size() + 1;
for (int i = 0; i < len; i++) {
for (int j = 0; j <= i; j++) c[i] += x[j] * y[i - j];
if (c[i] >= 10) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
}
while (c[len] == 0) len--;
}
int main() {
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i--) x[a.size() - 1 - i] = a[i] - '0';
for (int i = b.size() - 1; i >= 0; i--) y[b.size() - 1 - i] = b[i] - '0';
mul();
for (int i = len; i >= 0; i--) cout << c[i];
return 0;
}
vector版本
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int, int> PII;
const int N = 1e5 + 10, mod = 1e9 + 7;
vector<int> x, y;
string a, b;
int c[N];
int len;
void mul() {
len = a.size() + b.size() + 1;
while (x.size() < len) x.push_back(0);
while (y.size() < len) y.push_back(0);
//这里是为了保证下面取x[j]和y[i-j]不会报re
//数组模拟时长度足够长所以不需要考虑re的问题。
for (int i = 0; i < len; i++) {
for (int j = 0; j <= i; j++) c[i] += x[j] * y[i - j];
if (c[i] >= 10) {
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
}
while (c[len] == 0) len--;
}
int main() {
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i--) x.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) y.push_back(b[i] - '0');
// for (int i = 0; i < x.size(); i++) cout << x[i];
mul();
for (int i = len; i >= 0; i--) cout << c[i];
return 0;
}
//试除法求质数
bool is_prime(int n)
{
if(n<2) return false;
for(int i=2;i<sqrt(n);i++)
if(n%i==0)return false;
return true;
}
//埃氏筛法(1~n之间的质数)
void prime(int n)
{
memset(st,0,sizeof st);
for(int i=2;i<=n;i++)
{
if(st[i]) continue;
cout<<i<<endl;//i为质数
for(int j=i;j<=n/i;j++)st[i*j]=true;
}
}
//线筛法求质数
const int N=1e6+10;
bool st[N];
int primes[N],cnt;
void get_primes(int n)
{
memset(st,0,sizeof st);
cnt=0;
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[++cnt]=i;
for(int j=1;primes[j]<=n/i;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)break;//
}
}
}
//质因数分解
void div(int n)
{
m=0;
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
p[++m]=i,cnt[m]=0;
while(n%i==0)n/=i,cnt[m]++:
}
}
if(n>1)//n自身或最后剩的n也是质数的情况
p[++m]=n,cnt[m]=1;
}
求最大公约数
欧几里得算法:
int get_gcd(int a,int b)
{
return b?get_gcd(b,a%b):a;
}
定理:任意的a,b属于N,都有 gcd( a , b ) * lcm ( a , b ) = a * b;
任意的a,b属于N,都有gcd( 2 * a , 2 * b) = 2 * gcd( a , b );
更相损减术:任意的a,b(a>=b) ,都有gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)
扩展欧几里得算法:
应用方面:给定两个非零整数a,b,求一组整数x,y使得ax+by = gcd(a,b)成立,在欧几里得算法中,当b==0时就会返回a,此时a就是最大公约数,此时有x=1,y=0使得,ax+by=gcd(a,0)成立。
因为有ax+by==gcd(a,b)==gcd(b,a%b)==bx+(a%b)y
故ax+by==bx+(a%b)y
由此可以推出
ax+by==bx+(a-b(a/b))y==ay1+b(x1-(a/b)*y1)
因此可以令
x=y1;
y=x1-(a/b)*y1;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int exgcd(int a,int b,int &x,int &y)
{
if(b==0) { x=1,y=0;return a;}
int d=exgcd(b,a%b,x,y);
int z=x;
x=y;
y=z-y*(a/b);
return d;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a,b,x,y;
scanf("%d%d",&a,&b);
exgcd(a,b,x,y);
printf("%d %d\n",x,y);
}
return 0;
}
......................................................分界线——————————
欧拉函数:f(n)=1~n中与n互质的数的个数;
互质:gcd(n,i)=1 ,最大公约数为1;
性质1:任意n>1,1~n中与n互质的数和为n*f(n)/2;
性质2:若a,b互质,则f(a*b)=f(a)*f(b)
代码:
int phi(int n)
{
int ans=n;
for(int i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) ans=ans/n*(n-1);
return ans;
}