日常筆記(數學)

 

 

目錄

 

一  polya定理,Burnside引理   

二 拉格朗日插值法

三 線性齊次遞推(需要前2×k項)

三 線性基(交集)

四 Lucas定理(組合數)


        


一  polya定理,Burnside引理

 轉自:https://blog.csdn.net/whereisherofrom/article/details/79631703

1.Burnside引理:

                                       

               L代表m種顏色給n個對象染色的總方案數,|G|代表置換個數,|D(gi)|代表在gi這種置換作用下沒有改變狀態的方案個數。

 2,polya定理:

                                      

                            m種顏色給n個對象染色的方案數如圖所示。G代表變換(置換)的種類,其中Ci代表每種置換下的循環節。

   

二 拉格朗日插值法

參考博客:https://www.luogu.org/problemnew/solution/P4781

/*
	n+1個點可以確定一個n次多項式,給定n+1個點,求這個多項式的第k項
	fast_mod 快速冪 inv 逆元 X[],Y[] 點的座標
*/

ll calc(ll k) {
	ll ans = 0;
	for (int i = 0; i < n; i++) {
		ll s = Y[i]%mod,s1=1LL;
		for (int j = 0; j < n; j++) {
			if (i != j)s = s * (k - X[j]) % mod,s1=s1*((X[i]-X[j])%mod)%mod;
		}
		ans = (ans + s * inv(s1) % mod)%mod;
		ans = (ans + mod) % mod;
	}
	return ans;
}

 若x是連續的,則可以O(n)求解:

int lagrange(int n, int *x, int *y, int xi) {
    int ans = 0;
    s1[0] = (xi-x[0])%mod, s2[n+1] = 1;
    for (int i = 1; i <= n; i++) s1[i] = 1ll*s1[i-1]*(xi-x[i])%mod;
    for (int i = n; i >= 0; i--) s2[i] = 1ll*s2[i+1]*(xi-x[i])%mod;
    ifac[0] = ifac[1] = 1;
    for (int i = 2; i <= n; i++) ifac[i] = -1ll*mod/i*ifac[mod%i]%mod;
    for (int i = 2; i <= n; i++) ifac[i] = 1ll*ifac[i]*ifac[i-1]%mod;
    for (int i = 0; i <= n; i++)
        (ans += 1ll*y[i]*(i == 0 ? 1 : s1[i-1])%mod*s2[i+1]%mod
            *ifac[i]%mod*(((n-i)&1) ? -1 : 1)*ifac[n-i]%mod) %= mod;
    return (ans+mod)%mod;
}

 

struct lagrange {
    #define D 1100
    //D比MAXN大100就行
    ll a[D], f[D], g[D], p[D], p1[D], p2[D], b[D], h[D][2], C[D];
    void init(int M) {//初始化:參數填MAXN + 20
        f[0] = f[1] = g[0] = g[1] = 1;
        for(int i=2;i<M+5;i++)f[i] = f[i - 1] * i % mod;
        g[M + 4] = powmod(f[M + 4], mod - 2);
        for(int i=M+3;i>=1;i--)g[i] = g[i + 1] * (i + 1) % mod;
    }
    /*給定一組樣本數據a[],規模爲0-d,計算出第n項*/
    ll calcn(int d, ll *a, ll n) {
        if (n <= d) return a[n];
        p1[0] = p2[0] = 1;
        for(int i=0;i<d+1;i++){
            ll t = (n - i + mod) % mod;
            p1[i + 1] = p1[i] * t % mod;
        }
        for(int i=0;i<d+1;i++){
            ll t = (n - d + i + mod) % mod;
            p2[i + 1] = p2[i] * t % mod;
        }
        ll ans = 0;
        for(int i=0;i<=d;i++){
            ll t = g[i] * g[d - i] % mod * p1[i] % mod * p2[d - i] % mod * a[i] % mod;
            if ((d - i) & 1) ans = (ans - t + mod) % mod;
            else ans = (ans + t) % mod;
        }
        return ans;
    }
    /*
    給定一組觀測點(0, a[0]), (1, a[1]), ...,(m, a[m]),、
    樣本點的個數爲a(x)的最高次+1。
    求在該函數模型下,a[0]+a[1]+...+a[n]的和。
    */
    ll ta[D];
    ll polysum(ll m, ll *a, ll n) { // 給定a[0].. a[m],求\sum_{i=0}^{n}a[i]
        memcpy(ta, a, sizeof(a[0]) * (m + 1));
        ta[m + 1] = calcn(m, ta, m + 1);
        for(int i=1;i<m+2;i++)ta[i] = (ta[i - 1] + ta[i]) % mod;
        return calcn(m + 1, ta, n);
    }
};

  三 線性齊次遞推(需要前2×k項)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> P;
#define pu push
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define SZ(x) (int)x.size()
#define se second
#define rep(i, a, b) for (int i = (a); i < (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
#define repn(i, a, b) for (int i = (a); i <= (b); i++)
#define repv(i, v) for (auto i : v)
const int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
const int eps = 1e-7;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn = 1e2;

typedef vector<ll> VI;

ll powmod(ll a, ll b) {
    ll res = 1;
    a %= mod;
    assert(b >= 0);
    for (; b; b >>= 1) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
    }
    return res;
}
// head

int _, n;
namespace linear_seq {
    const int N=10010;
    ll res[N],base[N],_c[N],_md[N];

    vector<int> Md;
    inline void mul(ll *a,ll *b,int k) {
        for(int i=0;i<k+k;i++) _c[i]=0;
        for(int i=0;i<k;i++) if (a[i]) for(int j=0;j<k;j++) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
        for (int i=k+k-1;i>=k;i--) if (_c[i])
            for(int j=0;j<Md.size();j++) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
        for(int i=0;i<k;i++) a[i]=_c[i];
    }

    inline int solve(ll n,VI a,VI b) { // a 係數 b 初值 b[n+1]=a[0]*b[n]+...
        ll ans=0,pnt=0;
        int k=SZ(a);
        assert(SZ(a)==SZ(b));
        for(int i=0;i<k;i++) _md[k-1-i]=-a[i];_md[k]=1;
        Md.clear();
        for(int i=0;i<k;i++) if (_md[i]!=0) Md.push_back(i);
        rep(i,0,k) res[i]=base[i]=0;
        res[0]=1;
        while ((1ll<<pnt)<=n) pnt++;
        for (int p=pnt;p>=0;p--) {
            mul(res,res,k);
            if ((n>>p)&1) {
                for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                for(int j=0;j<Md.size();j++) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
            }
        }
        for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%mod;
        if (ans<0) ans+=mod;
        return ans;
    }

    inline VI BM(VI s) {
        VI C(1,1),B(1,1);
        int L=0,m=1,b=1;
        for(int n=0;n<s.size();n++) {
            ll d=0;
            for(int i=0;i<L+1;i++) d=(d+(ll)C[i]*s[n-i])%mod;
            if (d==0) ++m;
            else if (2*L<=n) {
                VI T=C;
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                for(int i=0;i<B.size();i++) C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                for(int i=0;i<B.size();i++) C[i+m]=(C[i+m]+c*B[i])%mod;
                ++m;
            }
        }
        return C;
    }
    
    
    inline int gao(VI a,ll n) {         //前2×k項,以及要求的第n項,返回結果;VI 是vector;
        VI c=BM(a);
        c.erase(c.begin());
        for(int i=0;i<c.size();i++) c[i]=(mod-c[i])%mod;
        return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
    }
};

    三 線性基(交集)

struct Line_base {
	ll b[M];
	Line_base (){
		memset(b,0,sizeof(b));
	}
	void Insert(ll x) {
		for (int i = 33; i >= 0; i--) {
			if (x&(1LL << i)) {
				if (b[i])x ^= b[i];
				else {
					b[i] = x;
					break;
				}
			}
		}
	}
	bool check(ll x) {
		for (int i = 33; i >= 0; i--) {
			if (x&(1LL << i)) {
				if (!b[i])return false;
				else x ^= b[i];
			}
		}
		return true;
	}
	//交集
	friend Line_base operator + (const Line_base &a, const Line_base &b){
		Line_base ans , c = b, d = b;
		for(int i=0;i< 34;i++)
		{
			ll x = a.b[i];
			if (!x)continue;
			int j = i; ll T = 0;
			for (; j >= 0; --j)
				if ((x >> j) & 1)
					if (c.b[j]) { x ^= c.b[j]; T ^= d.b[j]; }
					else break;
			if (!x)ans.b[i] = T;
			else { c.b[j] = x; d.b[j] = T; }
		}
		return ans;
	}
};

四 Lucas定理(組合數)

#define ll long long
const int N = 1e5 + 10;
ll mod, n, m;
ll fac[N];
void init() {
	fac[0] = 1;
	for (int i = 1; i <= mod; i++) fac[i] = fac[i - 1] * i%mod;
}
/*
	C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p 盧卡斯定理,模數不能太大,n,m可以大
*/
ll quik(ll x,ll n) {
	ll ans = 1;
	while (n) {
		if (n & 1)ans = ans * x%mod;
		n >>= 1;
		x = x * x%mod;
	}
	return ans;
}

ll C(ll n, ll m) {
	if (m > n)return 0;
	return fac[n] * quik(fac[m] * fac[n - m] % mod, mod - 2) % mod;
}

ll Lucas(ll n, ll m) {
	if (m == 0)return 1;
	return C(n%mod, m%mod)*Lucas(n / mod, m / mod) % mod;

}

五 Pollard's Rho算法(大數質因數分解)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;

typedef long long ll;
const int maxn = 105;
ll x[maxn], ans;
queue<ll> aria;
ll min(ll a, ll b)
{
	if (a < b)	return a;
	else	return b;
}
ll multi(ll a, ll b, ll p)	//快速乘? 
{
	ll ans = 0;
	while (b) {
		if (b & 1LL)	ans = (ans + a) % p;
		a = (a + a) % p;
		b >>= 1;
	}
	return ans;
}
ll qpow(ll a, ll b, ll p)
{
	ll ans = 1;
	while (b) {
		if (b & 1LL)	ans = multi(ans, a, p);
		a = multi(a, a, p);
		b >>= 1;
	}
	return ans;
}

bool MR(ll n)
{
	if (n == 2)	return true;
	int s = 20, i, t = 0;
	ll u = n - 1;
	while (!(u & 1)) {
		t++;
		u >>= 1;
	}
	while (s--) {
		ll a = rand() % (n - 2) + 2;
		x[0] = qpow(a, u, n);
		for (i = 1; i <= t; i++) {
			x[i] = multi(x[i - 1], x[i - 1], n);
			if (x[i] == 1 && x[i - 1] != 1 && x[i - 1] != n - 1)	return false;
		}
		if (x[t] != 1)	return false;
	}
	return true;
}

ll gcd(ll a, ll b)
{
	if (b == 0)	return a;
	else	return gcd(b, a%b);
}

ll Pollard_Rho(ll n, int c)
{
	ll i = 1, k = 2, x = rand() % (n - 1) + 1, y = x;
	while (1) {
		i++;
		x = (multi(x, x, n) + c) % n;
		ll p = gcd((y - x + n) % n, n);
		if (p != 1 && p != n)	return p;
		if (y == x)	return n;
		if (i == k) {
			y = x;
			k <<= 1;
		}
	}
}

void find(ll n, int c)
{
	if (n == 1)	return;
	if (MR(n)) {
		aria.push(n);
		return;
	}
	ll p = n, k = c;
	while (p >= n) {
		p = Pollard_Rho(p, c--);
	}
	find(p, k);
	find(n / p, k);
}

int main()
{
	ll n;
	while (~scanf("%lld", &n)) {
		find(n, 107);
		cout << aria.front();
		aria.pop();
		while (!aria.empty()) {
			cout << "*" << aria.front();
			aria.pop();
		}
		cout << endl;
	}
	return 0;
}

六 二次剩餘

#define ll long long
const ll p = 1e9 + 7;
ll w;
struct T { ll x, y; };

T mul_two(T a, T b, ll p) {
	T ans;
	ans.x = (a.x*b.x%p + a.y*b.y%p*w%p) % p;
	ans.y = (a.x*b.y%p + a.y*b.x%p) % p;
	return ans;
}

T qpow_two(T a, ll n, ll p) {
	T ans;
	ans.x = 1;
	ans.y = 0;
	while (n) {
		if (n & 1) ans = mul_two(ans, a, p);
		n >>= 1;
		a = mul_two(a, a, p);
	}
	return ans;
}

ll qpow(ll a, ll n, ll p) {
	ll ans = 1;
	a %= p;
	while (n) {
		if (n & 1) ans = ans * a%p;
		n >>= 1;
		a = a * a%p;
	}
	return ans % p;
}

ll Legendre(ll a, ll p) {
	return qpow(a, (p - 1) >> 1, p);
}

ll solve(ll n, ll p) {
	if (n == 0) return 0;
	if (n == 1) return 1;
	if (Legendre(n, p) + 1 == p) return -1;
	ll a, t;
	while (1) {
		a = rand() % p;
		t = a * a - n;
		w = (t%p + p) % p;
		if (Legendre(w, p) + 1 == p) break;
	}
	T tmp;
	tmp.x = a;
	tmp.y = 1;
	T ans = qpow_two(tmp, (p + 1) >> 1, p);
	return ans.x;
}

七 多邊形求交

//點按順時針或者逆時針給出
#include<bits/stdc++.h>
using namespace std;
#define maxn 510
const double eps = 1E-8;
int sig(double d) {
	return(d > eps) - (d < -eps);
}
struct Point {
	double x, y; Point() {}
	Point(double x, double y) :x(x), y(y) {}
	bool operator==(const Point&p)const {
		return sig(x - p.x) == 0 && sig(y - p.y) == 0;
	}
};
double cross(Point o, Point a, Point b) {
	return(a.x - o.x)*(b.y - o.y) - (b.x - o.x)*(a.y - o.y);
}
double area(Point* ps, int n) {
	ps[n] = ps[0];
	double res = 0;
	for (int i = 0; i < n; i++) {
		res += ps[i].x*ps[i + 1].y - ps[i].y*ps[i + 1].x;
	}
	return res / 2.0;
}
int lineCross(Point a, Point b, Point c, Point d, Point&p) {
	double s1, s2;
	s1 = cross(a, b, c);
	s2 = cross(a, b, d);
	if (sig(s1) == 0 && sig(s2) == 0) return 2;
	if (sig(s2 - s1) == 0) return 0;
	p.x = (c.x*s2 - d.x*s1) / (s2 - s1);
	p.y = (c.y*s2 - d.y*s1) / (s2 - s1);
	return 1;
}
//多邊形切割
//用直線ab切割多邊形p,切割後的在向量(a,b)的左側,並原地保存切割結果
//如果退化爲一個點,也會返回去,此時n爲1
void polygon_cut(Point*p, int&n, Point a, Point b) {
	static Point pp[maxn];
	int m = 0; p[n] = p[0];
	for (int i = 0; i < n; i++) {
		if (sig(cross(a, b, p[i])) > 0) pp[m++] = p[i];
		if (sig(cross(a, b, p[i])) != sig(cross(a, b, p[i + 1])))
			lineCross(a, b, p[i], p[i + 1], pp[m++]);
	}
	n = 0;
	for (int i = 0; i < m; i++)
		if (!i || !(pp[i] == pp[i - 1]))
			p[n++] = pp[i];
	while (n > 1 && p[n - 1] == p[0])n--;
}
//---------------華麗的分隔線-----------------//
//返回三角形oab和三角形ocd的有向交面積,o是原點//
double intersectArea(Point a, Point b, Point c, Point d) {
	Point o(0, 0);
	int s1 = sig(cross(o, a, b));
	int s2 = sig(cross(o, c, d));
	if (s1 == 0 || s2 == 0)return 0.0;//退化,面積爲0
	if (s1 == -1) swap(a, b);
	if (s2 == -1) swap(c, d);
	Point p[10] = { o,a,b };
	int n = 3;
	polygon_cut(p, n, o, c);
	polygon_cut(p, n, c, d);
	polygon_cut(p, n, d, o);
	double res = fabs(area(p, n));
	if (s1*s2 == -1) res = -res; return res;
}
//求兩多邊形的交面積
double intersectArea(Point*ps1, int n1, Point*ps2, int n2) {
	if (area(ps1, n1) < 0) reverse(ps1, ps1 + n1);
	if (area(ps2, n2) < 0) reverse(ps2, ps2 + n2);
	ps1[n1] = ps1[0];
	ps2[n2] = ps2[0];
	double res = 0;
	for (int i = 0; i < n1; i++) {
		for (int j = 0; j < n2; j++) {
			res += intersectArea(ps1[i], ps1[i + 1], ps2[j], ps2[j + 1]);
		}
	}
	return res;//assumeresispositive!
}
//hdu-3060求兩個任意簡單多邊形的並面積
Point p1[maxn], p2[maxn];
int a, b, c, d, e, f, g, h;
int main() {
	int i;
	while (scanf("%d%d%d%d%d%d%d%d", &a, &b, &c, &d, &e, &f, &g, &h) != EOF) {
		p1[0].x = a; p1[0].y = b; p1[1].x = a; p1[1].y = d; p1[2].x = c; p1[2].y = b;
		p2[0].x = e; p2[0].y = f; p2[1].x = e; p2[1].y = h; p2[2].x = g; p2[2].y = h; p2[3].x = g; p2[3].y = f;
		printf("%.8lf\n", intersectArea(p1, 3, p2, 4));
	}
	return 0;
}

八 兩圓面積交

#include <bits/stdc++.h>
using namespace std;
#define Pi acos(-1.0)
using namespace std;
int main(){
    double x1,x2,r1,r2,y1,y2;//定義兩圓心及半徑
    while (scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&r1,&x2,&y2,&r2)!=EOF){//輸入
        double x=abs(x1-x2);    //求出X差
        double y=abs(y1-y2);    //求出Y差
        double l=sqrt(x*x+y*y); //求和距離
        if (r1<r2) swap(r1,r2); //保證R1<R2
        if (r1+r2<=l) printf("0.000\n");//兩圓分離
        else if (abs(r1-r2)>=l) printf("%.3f\n",Pi*min(r1*r1,r2*r2));//包含關係
        else {//否則就是相交
            double a=r1,b=r2,c=l;//A是半徑一,B是半徑二
            double A=acos((c*c+b*b-a*a)/(2*c*b));//讀出圓一的交弧角度
            double B=acos((c*c+a*a-b*b)/(2*c*a));//讀出圓二的交弧角度
            double s=(a+b+c)/2;         //求出三角形周長一半
            s=sqrt(s*(s-a)*(s-b)*(s-c));//海勒公式求面積,這個三角形是底是圓心距,高是連心線到交點垂線距
            double area=a*a*B+b*b*A-2*s;//求出答案
            printf("%.3f\n",area);      //輸出
        }//基本思路就是兩圓減去兩個三角形
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章