1:欧拉函数
含义:phi[n]代表小于等于n的数中与n互质的数的数目,phi[1]=1.
性质:若n是素数p的k次方:phi[n]=p^k-p^(k-1)=(p-1)*(p^(k-1))
若m,n互质,则phi[m*n]=phi[n]*phi[m].
公式:令p为n的最小质因数,若p^2|n,则phi[n]=phi[n/p]*p,否则phi[n]=phi[n/p]*(p-1).
const int maxn = 4000010; ll vis[maxn+100],phi[maxn+100],prime[maxn+100],tot; //标记是否为素数,欧拉函数值,素数存放,素数总个数 void Getphi() //O(n) { phi[1]=1; for(int i=2;i<=maxn;i++){ if(!vis[i]){ //素数的欧拉函数值为i-1 prime[++tot]=i; phi[i]=i-1; } for(int j=1;j<=tot&&i*prime[j]<=maxn;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } else{ phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } } ll minDiv[maxn+100],phi[maxn+100]; void Getphi() //O(nlog n) { for(int i=1;i<maxn;i++)minDiv[i]=i; for(int i=2;i*i<=maxn;i++){ if(minDiv[i]==i){ for(ll j=i*i;j<=maxn;j+=i){ minDiv[j]=i; } } } phi[1]=1; for(int i=2;i<=maxn;i++){ phi[i]=phi[i/minDiv[i]]; if((i/minDiv[i])%minDiv[i]==0){ phi[i]*=minDiv[i]; } else{ phi[i]*=minDiv[i]-1; } } }
2:扩展欧几里德:
ll exgcd(ll a,ll b,ll &x,ll &y)//a*x+b*y=gcd(a,b)的解 { ll d=a; if(b!=0){ d=exgcd(b,a%b,x,y); ll temp=x; x=y; y=temp-a/b*y; } else x=1,y=0; return d; } void cal(ll a,ll b,ll c)//a*x+b*y=c的解 { ll x,y; ll g = exgcd(a,b,x,y); if(c%g)cout<<"此方程无解"<<endl; else{ x *= c/g; b /= g; if(b<0)b = -b; x %= b; if(x<=0)x += b; cout << x << endl; } }
3:素数筛:
void Getprime()//埃式筛法,O(nloglogn),近似线性 { for(int i=1;i<=maxn;i++)is_prime[i]=1; is_prime[1]=0; for(int i=2;i<=maxn;i++){ if(is_prime[i]){ prime[++tot]=i; for(int j=2*i;j<=maxn;j+=i)is_prime[j]=0; } } } void Getprime()//O(n) { memset(is_prime,1,sizeof(is_prime)); is_prime[1]=0; for(int i=2;i<=maxn;i++){ if(is_prime[i]){ prime[++tot]=i; } for(int j=1;j<=tot&&i*prime[j]<=maxn;j++){ is_prime[i*prime[j]]=0; if(i%prime[j]==0)break; } } }
4:质因数分解:
int a[maxn],b[maxn],tot; void factor(int n)//将n质因子分解,1需要特判 { int now=n; for(int i=2;i*i<=n;i++){ if(now%i==0){ a[++tot]=i; while(now%i==0){ ++b[tot]; now/=i; } } } if(now!=1){ a[++tot]=now; ++b[tot]; } }
5:lucas定理:
ll fac[maxn]; void Init() { fac[0]=1; for(int i=1;i<=maxn;i++){ fac[i]=fac[i-1]*i%mod; } } ll inv(ll a,ll m) { if(a==1)return 1; return inv(m%a,m)*(m-m/a)%m; } ll lucas(ll n,ll m,ll mod) { ll ans=1; while(n&&m){ ll a=n%mod; ll b=m%mod; if(a<b)return 0; ans=ans*fac[a]%mod*inv(fac[b]*fac[a-b]%mod,mod)%mod; n/=mod; m/=mod; } return ans; }
6:求幂塔公式:a^(a^(a^(a^...))))总共有b个a,结果对m取模
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+5; typedef long long ll; bitset<maxn>notprime; int phi[maxn],prime[maxn],cnt=0; void pre(){ phi[1]=1; for(int i=2;i<=maxn-5;i++){ if(!notprime[i]){ prime[++cnt]=i; phi[i]=i-1;//i为素数时,phi[i]=i-1 } for(int j=1;j<=cnt&&prime[j]*i<=maxn;j++){ notprime[i*prime[j]]=1; if(i%prime[j]==0){//每个数只被它的最小质因数给筛掉 phi[i*prime[j]]=phi[i]*prime[j]; //当a与b互质时,满足phi(a∗b)=phi(a)∗phi(b),积性函数 break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); //phi[i∗prime[j]]=phi[i]∗phi[prime[j]]=phi[i]∗(prime[j]−1); } } } ll quick_mod(ll a,ll n,ll mod) { ll res=1; while (n) { if(n&1)res=res*a%mod; a=a*a%mod; n>>=1; // if(n&1)res=res*a>mod?res*a%mod+mod:res*a; // a=a*a>mod?a*a%mod+mod:a*a; // n>>=1;//这里保证了a与m不互质的情况? } return res; } ll deal(ll a,ll b,ll m) { if(b==0)return 1; if(m==1)return 1; ll res=deal(a,b-1,phi[m]); return quick_mod(a,res,m); } int main(){ pre(); int t; cin>>t; ll a,b,m; while (t--) { cin>>a>>b>>m; cout<<deal(a,b,m)%m<<endl; } return 0; }
7:ST表RMQ
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=100010; int ST[maxn][40]; int a[maxn]; void Init1(int n)//区间最值初始化 { for(int j = 1;(1<<j) <= n;j++){ for(int i = 1;i+(1<<j)-1 <= n;i++){ ST[i][j]=max(ST[i][j-1],ST[i+(1<<(j-1))][j-1]); } } } int query(int l,int r)//询问区间最值 { int k=(int)(log(r-l+1)/log(2.0)); return max(ST[l][k],ST[r+1-(1<<k)][k]); } void Init2(int n)//区间求和初始化 { for(int j = 1;(1<<j) <= n;j++){ for(int i = 1;i+(1<<j)-1 <= n;i++){ ST[i][j]=ST[i][j-1]+ST[i+(1<<(j-1))][j-1]; } } } int sum(int l,int r)//区间求和 { int ans=0; for(int i=20;i>=0;i--){ if(l+(1<<i)>r)continue; ans+=ST[l][i]; l+=(1<<i); } return ans+ST[l][0]; } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); ST[i][0]=a[i]; } Init2(n); while(m--){ int l,r; scanf("%d%d",&l,&r); printf("%d\n",sum(l,r)); } return 0; }
BM线性递推模板:
#include<bits/stdc++.h> #define mp make_pair #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) using namespace std; typedef vector<int> VI; typedef long long ll; typedef pair<int, int> PII; const ll mod = 1000000007; 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 ll n; namespace linear_seq { const int N = 10010; ll res[N], base[N], _c[N], _md[N]; vector<int> Md; void mul(ll *a, ll *b, int k) { rep(i, 0, k + k) _c[i] = 0; rep(i, 0, k) if (a[i]) rep(j, 0, k) _c[i + j] = (_c[i + j] + a[i] * b[j]) % mod; for (int i = k + k - 1; i >= k; i--) if (_c[i]) rep(j, 0, SZ(Md)) _c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod; rep(i, 0, k) a[i] = _c[i]; } int solve(ll n, VI a, VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+... // printf("%d\n",SZ(b)); ll ans = 0, pnt = 0; int k = SZ(a); assert(SZ(a) == SZ(b)); rep(i, 0, k) _md[k - 1 - i] = -a[i]; _md[k] = 1; Md.clear(); rep(i, 0, k) 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; rep(j, 0, SZ(Md)) res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % mod; } } rep(i, 0, k) ans = (ans + res[i] * b[i]) % mod; if (ans<0) ans += mod; return ans; } VI BM(VI s) { VI C(1, 1), B(1, 1); int L = 0, m = 1, b = 1; rep(n, 0, SZ(s)) { ll d = 0; rep(i, 0, L + 1) 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); rep(i, 0, SZ(B)) 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); rep(i, 0, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod; ++m; } } return C; } int gao(VI a, ll n) { VI c = BM(a); c.erase(c.begin()); rep(i, 0, SZ(c)) c[i] = (mod - c[i]) % mod; return solve(n, c, VI(a.begin(), a.begin() + SZ(c))); } }; int main() { vector<int> V; int a[] = {2, 24, 96, 416, 1536, 5504, 18944, 64000, 212992, 702464, 2301952}; cin >> n; for(int i = 0; i <= 10; i++) V.push_back(a[i]); printf("%lld\n", 1ll * linear_seq::gao(V, n - 1)%mod); }