# 18寒假的数论

1.容斥原理找1到M中与N互质的数

int primes[33], ptot;
vector<pair<int,int> > split(int n) {
vector<pair<int,int> > stk;
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
stk.push_back(make_pair(i, 0));//一维表示因子，二维表示个数
while(n % i == 0) {
n /= i;
stk.back().second++;
}
}
}
if(n != 1) {
stk.push_back(make_pair(n, 1));//特判
}
return stk;
}

void print(int s) {
for(int i = 7; i >= 0; i--)
printf("%d", (s>>i)&1);
printf("\n");
}

void subset(int u) {
//    int u = 0x5;    //0x5 = 5    0000 0101
for(int s = u; s; s = (s - 1) & u) {
print(s);
}
print(0);
}
*/

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

int countbits(int s) {
int rt = 0;
while(s) {
rt++;
s -= s & -s;
}
return rt;
}
int count(int m, int n) {
vector<int> stk;
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
stk.push_back(i);
while(n % i == 0)
n /= i;
}
}
if(n != 1) stk.push_back(n);
if(stk.size() == 0) return 1;
int rt = 0;
int u = (1<<stk.size()) - 1;//造全集
for(int s = u; s; s = (s - 1) & u) {//造子集
int mul = 1;
for(int t = 0; t < (int)stk.size(); t++)
if((s>>t) & 1) mul *= stk[t];
if(countbits(s) & 1) //奇加偶减
rt += m / mul;
else
rt -= m / mul;
}
return m - rt;
}

int main() {
while(1) {
int m, n;
scanf("%d%d", &m, &n);
printf("%d\n", count(m,n));
}
}

2.矩阵快速幂

#include <bits/stdc++.h>

using namespace std;
#define ll long long
ll a0,a1,a2,b,c,d,e,n;
const ll M = 1000000000000000000LL;
struct Maxtri{
ll w[4][4];
void unit() {//单位矩阵
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
w[i][j] = (i == j);
}
ll *operator[](int i){
return w[i];
}
};
ll c = a + b;
if(c >= M)c -= M;
return c;
}
ll quick(ll a,ll b){
ll rt = 0;
return rt;
}
Maxtri operator*(Maxtri l, Maxtri r){
Maxtri c;
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++){
c[i][j] = 0;
for(int k = 0; k < 4; k++)
c[i][j] = add( c[i][j] , quick(l[i][k], r[k][j]) );
}
return c;

}
Maxtri mul(ll b, Maxtri a){
Maxtri rt;
for(rt.unit(); b; b>>=1, a=a*a)
if(b & 1) rt = rt*a;
return rt;

}
int main(){
//freopen("seq.in","r",stdin);
//freopen("seq.out","w",stdout);
scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a0,&a1,&a2,&b,&c,&d,&e,&n);
Maxtri a;
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
a[i][j] = 0;
a[2][0] = d, a[2][1] = c, a[2][2] = b, a[2][3] = e;
a[0][1] = a[1][2] = a[3][3] = 1;//初始矩阵
Maxtri q = mul(n, a);
Maxtri p;
p[0][0] = a0, p[0][1] = a1, p[0][2] = a2,p[0][3] = 1;//向量
ll ans = 0;
for(int i = 0; i < 4; i++)
ans = add(ans, quick( q[0][i] , p[i][0] ));//最后点乘向量
stringstream ss;
string sans;
ss << ans;
ss >> sans;
for(int i = 1; i < 18 - (int)sans.size(); i++)
printf("0");
cout<<sans<<endl;
return 0;
}

const int Mod = 1e9 + 7;

struct Matrix {
int w[2][2];
void zero() {
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
w[i][j] = 0;
}
void unit() {//构造单位矩阵，不是初始矩阵
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
w[i][j] = (i == j);
}
int *operator[](int i) {//重载【】
return w[i];
}
};

Matrix operator*(const Matrix &r, const Matrix &s) {//重载乘号
Matrix c;
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++) {
c[i][j]  = 0;
for(int k = 0; k < 2; k++)
c[i][j] = (c[i][j] + 1LL * r[i][k] * s[k][j])% Mod;
}
return c;
}

Matrix mpow(Matrix a, int b) {//矩阵快速幂
Matrix rt;
for(rt.unit(); b; b>>=1,a=a*a)
if(b & 1) rt=rt*a;
return rt;
}

#include <bits/stdc++.h>
using namespace std;

const int N = 1000100;

namespace NT {
bool isnot[N];
int mu[N], phi[N];
int primes[N], ptot;
//筛素数
void normal_sieve( int n ) {
isnot[1] = true;
for( register int i = 2; i <= n; i++ ) {
if( !isnot[i] ) {
for( register int j = i + i; j <= n; j += i ) {
isnot[j] = true;
}
}
}
}
void linear_sieve( int n ) {
isnot[1] = true;
for( int i = 2; i <= n; i++ ) {
if( !isnot[i] ) //isnot是合数
primes[ptot++] = i;
for( int t = 0; t < ptot; t++ ) {
int j = primes[t] * i;
if( j > n ) break;
isnot[j] = true;
if( i % primes[t] == 0 )
break;
}
}
}
void linear_sieve_more( int n ) {
isnot[1] = true;
mu[1] = 1;
phi[1] = 1;
for( int i = 2; i <= n; i++ ) {
if( !isnot[i] ) {
primes[ptot++] = i;
mu[i] = -1;
phi[i] = i - 1;
}
for( int t = 0; t < ptot; t++ ) {
int j = primes[t] * i;
if( j > n ) break;
isnot[j] = true;
mu[j] = mu[primes[t]] * mu[i];
phi[j] = phi[primes[t]] * phi[i];
if( i % primes[t] == 0 ) {
mu[j] = 0;
phi[j] = primes[t] * phi[i];
break;
}
}
}
}

//    greatest common divisor
long long gcd( long long a, long long b ) {
return b == 0 ? a : gcd( b, a % b );
}

long long lcm( long long a, long long b ) {
return a / gcd(a,b) * b;//先除后乘
}

//    gcd(a,b) = a * x + b * y
long long exgcd( long long a, long long b, long long &x, long long &y ) {
if( b == 0 ) {
x = 1;
y = 0;
return a;
} else {
long long x0, y0;
long long cd = exgcd( b, a % b, x0, y0 );
x = y0;
y = x0 - (a/b) * y0;
return cd;
}
}
int main() {
int a, b;
while( scanf("%d%d",&a,&b) == 2 ) {
long long x, y;
long long cd = exgcd(a,b,x,y);
printf( "%lld = %d * %lld + %d * %lld\n", cd, a, x, b, y );
}
}

//    ax + by = c
bool linear_equation( long long a, long long b, long long c, long long &x, long long &y, long long &xinc, long long &yinc ) {
long long d = gcd(a,b);
if( c % d != 0 ) return false;
a /= d, b /= d, c /= d;
exgcd( a, b, x, y );
x *= c;
y *= c;
xinc = b;
yinc = -a;
return true;
}

//    lucas't theorem
//    C(n,m) = C(n / p, m / p) * C(n % p, m % p) ( mod p )    when 0 <= m <= n
//    C(n,m) = 0 ( mod p )    when m > n
long long fac[N], vfac[N];
// 求组合数
/* 暴力
long long comb[N][N];

void init(int n) {
for(int i = 0; i <= n; i++) {
for(int j = 0; j <= i; j++) {
if(j == 0 || j == i)
comb[i][j] = 1;
else
comb[i][j] = (comb[i-1][j-1] + comb[i-1][j]) % Mod;
}
}
}
*/
//公式
long long comb( long long n, long long m, long long p ) {
if( m > n ) return 0;
return fac[n] * vfac[m] % p * vfac[n-m] % p;
}
long long lucas( long long n, long long m, long long p ) {
if( m > n ) return 0;
if( n / p == 0 ) return 1;//key point!
return lucas( n / p, m / p, p ) * comb( n % p, m % p, p ) % p;
}
}
long long exgcd( long long a, long long b, long long &x, long long &y ) {
if( b == 0 ) {
x = 1;
y = 0;
return a;
} else {
long long x0, y0;
long long cd = exgcd( b, a % b, x0, y0 );
x = y0;
y = x0 - (a/b) * y0;
return cd;
}
}

//    a^(-1)
/* way 1
long long inverse( long long a, long long mod ) {    //    require mod is a prime
return mpow(a, mod-2, mod);
}
*/
// way 2
long long inverse( long long a, long long mod ) {
long long x, y;
exgcd( a, mod, x, y );
return (x % mod + mod) % mod;
}

//    Chinese Remainder Theorem
//    x = a ( mod m )
long long crt( vector<long long> va, vector<long long> vm ) {
int n = (int)va.size();
long long M = 1;
for( int t = 0; t < n; t++ )
M *= vm[t];
long long ans = 0;
for( int t = 0; t < n; t++ ) {
long long ci = M / vm[t];
long long invci = inverse(ci,vm[t]);
ans = (ans + ci * invci % M * va[t])% M;
}
return ans;
}

int main() {
vector<long long> va, vm;
va.push_back(2);vm.push_back(3);
va.push_back(3);vm.push_back(5);
va.push_back(0);vm.push_back(4);
long long ans = crt(va, vm);
printf("%I64d\n", ans);
}

exgcd:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

https://blog.csdn.net/shengtao96/article/details/51234355

CRT :http://yzmduncan.iteye.com/blog/1323599/

catalan:https://blog.csdn.net/doc_sgl/article/details/8880468

//直接求解欧拉函数
int euler(int n){ //返回euler(n)
int res=n,a=n;
for(int i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
} 
euler[1]=1;
for(int i=2;i<Max;i++)
euler[i]=i;
for(int i=2;i<Max;i++)
if(euler[i]==i)
for(int j=i;j<Max;j+=i)
euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出     

posted @ 2018-02-18 18:58  Ed_Sheeran  阅读(129)  评论(0编辑  收藏