数学模板整理

/*****************
数学整理
*****************/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+5;
//< 1 > 大数 (Java)
/*******
import java.util.*;
import java.math.*;
import java.lang.*;

public class Main{

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner cin = new Scanner(System.in);
		int b;

		while(cin.hasNext()){
			String s=cin.next();
			BigDecimal a=new BigDecimal(s);
			b=cin.nextInt();
			BigDecimal n=a.pow(b);

			String ans=n.stripTrailingZeros().toPlainString();
			if(ans.startsWith("0"))ans=ans.substring(1);
			System.out.println(ans);
		}
	}
}
*******/
/*
注意:使用java大数类解决问题时我们需要注意两个方面
1、不能有包名,也就是说我们要把主类放到默认的包里,

2、提交的类的类名必须为Main,如果是其他的名字你有可能收获到CE也有可能收获到WA

*/

/************************************
1、新建一个值为123的大整数对象
BigInteger a=new BigInteger(“123”);  //第一种,参数是字符串
BigInteger a=BigInteger.valueOf(123);    //第二种,参数可以是int、long

2、大整数的四则运算
a. add(b);    //a,b均为BigInteger类型,加法
a.subtract(b);   //减 法
a.divide(b);  //除法
a.multiply(b);    //乘法

3、大整数比较大小
a.equals(b);  //如果a、b相等返回true否则返回false
a.compareTo(b);  //a小于b返回-1,等于返回0,大于返回1

4、常用方法
 a.mod(b);  //求余
 a.gcd(b);  //求最大公约数
 a.max(b);  //求最大值
 a.min(b);  //求最小值
 a.pow(n);  //求a的n次方 (n : int)

5、BigInteger中的常数
BigInteger.ZERO    //大整数0
BigInteger.ONE    //大整数1
BigInteger.TEN   //大整数10

6、求大整数的位数
//先转换成字符串再求字符串的长度
a.toString().length();   //a的类型为BigInteger

//------------------
输入框架

场景一:不断读入数据直至文件尾,或者说有多组测试用例以EOF为结束标志
    Scanner cin = new Scanner(System.in); //相当于C++中的cin,只不过这个cin需要自己创建
    while(cin.hasNext()){  //等同于!=EOF
        BigInteger a;
        BigDecimal b;
        a = cin.nextBigInteger();   //读入一个BigInteger;
        b = cin.nextBigDecimal();   //读入一个BigDecimal;
        System.out.println(a);   //输出a并换行
    }

场景二:输入一个整数T,代表有T组测试样例
    Scanner cin = new Scanner(System.in);
    int T = cin.nextInt();
    while (T-- > 0) {
    	String s = cin.next();
    	BigInteger a = new BigInteger(s);
        System.out.println(a.toString());
    }
******************/
//< 2 > 快速乘/幂
ll mul(ll a, ll b, ll mod) {
	ll res = 0;
	while (b > 0) {
		if (b & 1) res = (res + a) % mod;
		b = b >> 1;
		a = a + a % mod;
	}
	return res;
}
ll qpow(ll a, ll b, ll mod) {
	ll res = 1;
	while (b > 0) {
		if (b & 1) res = mul(res, a, mod);
		b = b >> 1;
		a = mul(a, a, mod);
	}
	return res;
}
//光速幂
//a[n] = 233 a[n - 1] + 666 a[n - 2]
/*
1.列出特征方程,解方程。得到x1,x2;
2.a[n] = k1 * x1 ^ n + k2 * x2 ^ n;代入n=0,1求得k1,k2;
3.去除k1,k2中的无理数(暴力或是欧拉均可)
4.得到a[n] = k * (p ^ n - q ^ n)
5.里面两个底数的n次方如何O(1)求?分段打表 

Mod :模数   alpha : k
x_1 :p      x_2   : q
x_3 :qpow(x_1, 65536, Mod)
x_4 :qpow(x_2, 65536, Mod) 
*/ 
namespace Maker {
	unsigned long long SA, SB, SC;
	void init() {
		scanf("%llu%llu%llu", &SA, &SB, &SC);
	}
	inline unsigned long long rand() {
		SA ^= SA << 32, SA ^= SA >> 13, SA ^= SA << 1;
		unsigned long long t = SA;
		SA = SB, SB = SC, SC ^= t ^ SA;
		return SC;
	}
}

const int Mod = 1e9 + 7;
const int alpha = 233230706;
const int x_1 = 94153035;
const int x_2 = 905847205; 
const int x_3 = 64353223;
const int x_4 = 847809841;
const int maxn = 65536 + 5;
int f_1[maxn], f_2[maxn], f_3[maxn], f_4[maxn], T, ans;

inline int Pow_1(int x) {
	return 1ll * f_3[x >> 16] * f_1[x & 65535] % Mod;
}
inline int Pow_2(int x) {
	return 1ll * f_4[x >> 16] * f_2[x & 65535] % Mod;
}

int main() {
	f_1[0] = f_2[0] = f_3[0] = f_4[0] = 1;
	for(int i = 1; i < 65536; i++) f_1[i] = 1ll * f_1[i - 1] * x_1 % Mod;
	for(int i = 1; i < 65536; i++) f_2[i] = 1ll * f_2[i - 1] * x_2 % Mod;
	for(int i = 1; i < 65536; i++) f_3[i] = 1ll * f_3[i - 1] * x_3 % Mod;
	for(int i = 1; i < 65536; i++) f_4[i] = 1ll * f_4[i - 1] * x_4 % Mod;
	scanf("%d", &T);
	Maker::init();
	unsigned long long n;
	while(T--) {
		//欧拉降幂 
		n = Maker::rand() % (Mod - 1);
		ans ^= 1ll * alpha * (Pow_1(n) - Pow_2(n) + Mod) % Mod;
	}
	printf("%d\n", ans);
	return 0;
}
//< 3 > 筛法 && 素数
//反素数
void dfs(int dep,ll tmp,int num,int limit) { //dep表示到第几个素数,
	//tmp表示当前可能ans值,num表示因子数
	if(dep>=16) return;//深度达到最大
	if(num>best) { //best记的是当前最优num,有更优就更新
		best=num;
		ans=tmp;
	}
	//当因子个数相同时,取值最小的
	if(num==best&&ans>tmp) ans=tmp;
	for(int i=1; i<=limit; i++) {
		if(n/p[dep]<tmp) break;
		dfs(dep+1,tmp*=p[dept],num*(i+1));
	}
}
//欧拉筛法 素数筛 O(n)
int Euler_shai() {
	int tot = 0;
	int n = 1e3+1;
	memset(check, 0, sizeof check);
	for(int i = 2; i <= n; ++i) {
		if(!check[i]) {
			pri[tot++] = i;
		}
		for(int j = 1; j < tot; ++j) {
			if(i * pri[j] > n) break;
			check[i * pri[j]] = 1 ;
			if(i % pri[j] == 0) break;
		}
	}
}
//大素数测试
bool Miller_Rabin(ll n) {   //Miller_Rabin
	ll t,u,s = 10;
	if(n == 2 || n == 3) return true;
	if(n < 2 || !(n & 1)) return false;
	for(t = 0,u = n-1; !(u&1); t++, u >>= 1);  //n-1 = u*2^t
	for(int i = 0; i < s; i++) {
		ll a = rand() % (n - 1) - 1;
		ll x = qpow(a, u, n);   //a^u
		for(ll j = 0; j < t; j++) {
			ll y = mul(x, x, n);  //x^2
			if(y == 1 && x != 1 && x != n-1) return false;  //二次探测
			x = y;
		}
		if(x != 1) return false;    //费马小定理
	}
	return true;
}
//大整数分解
ll Pollard_Rho(ll n,ll c) {
	ll i = 1, j = 2;
	ll x = rand() % (n - 1) + 1, y = x;//随机初始化一个基数(p1)
	while(1) {
		i++;
		x=(mul(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;//y为x的备份,相等则说明遇到圈,退出
		if(i == j) {
			y = x;
			j <<= 1;
		}//更新y,判圈算法应用
	}
}
vector <ll> ans;
void find(ll n,ll c) { //同上,n为待分解数,c为随机常数
	if(n == 1) return;
	if(Miller_Rabin(n)) { //n为质数
		ans.push_back(n);
		return;
	}
	ll x = n, k = c;
	while(x==n)
		x = Pollard_Rho(x, c--);//当未分解成功时,换个c带入算法
	find(n/x, k);
	find(x, k);			//递归操作
}
//因子数
ll Divisors_num(ll n, int tot) { //素数总数
	ll ans = 1;
	for(int i = 0; i < tot && prime[i] * prime[i] <= n; i++) {
		if(n % prime[i] == 0) {
			int cnt = 0;
			while(n % prime[i] == 0) {
				cnt++;
				n /= prime[i];
			}
			ans *= (cnt + 1);
		}
	}
	if(n > 1)ans *= 2;
	return ans;
}
//因子和
ll Divisors_sum(ll n, int tot) {
	ll ans = 1;
	for(int i = 0; i < tot && prime[i] * prime[i] <= n; i++) {
		if(n % prime[i] == 0) {
			int cnt = 0;
			while(n % prime[i] == 0) {
				cnt++;
				n /= prime[i];
			}
			ans = (qpow(prime[i], cnt + 1) - 1) / (prime[i] - 1) * ans;
		}
	}
	if(n > 1)ans *= (n + 1);
	return ans;
}
//大数区间素数筛法 [L,R] O(n)
vector <ll> getprime(ll n, ll m) {
	vector <ll> pri;
	bitset <maxn> used(0), rused(0);
	ll len = sqrt(m);
	for(int i = 2; i <= len; ++i) {
		if(!used[i]) {
			ll x = i, y = max(x, x * (n / x));
			while(y <= m) {
				if(y - n >= 0 && y != x)
					rused[y - n] = true;
				y += x;
			}
			for(int j = 2 * i; j <= len; j += i) {
				used[j] = true;
			}
		}
	}
	for(int i = 0; i <= m - n; ++i) {
		if(i + n >= 2 && !rused[i])
			pri.push_back(i + n);
	}
	return pri;
}
//欧拉 函数打表
void phi_table(int n, int* phi) {
	for (int i = 2; i <= n; i++) phi[i] = 0;
	phi[1] = 1;
	for (int i = 2; i <= n; i++)
		if (!phi[i])
			for (int j = i; j <= n; j += i) {
				if (!phi[j]) phi[j] = j;
				phi[j] = phi[j] / i * (i - 1);
			}
}
//求单个欧拉函数
int euler_phi(int n) {
	int m = (int)sqrt(n + 0.5);
	int ans = n;
	for(int i = 2; i <= m; 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;
}
//莫比乌斯筛法
void pre() {
	mu[1] = 1;
	for (int i = 2; i <= 1e7; ++i) {
		if (!v[i]) mu[i] = -1, p[++tot] = i;
		for (int j = 1; j <= tot && i <= 1e7 / p[j]; ++j) {
			v[i * p[j]] = 1;
			if (i % p[j] == 0) {
				mu[i * p[j]] = 0;
				break;
			}
			mu[i * p[j]] = -mu[i];
		}
	}
}
//< 3 > 同余与同余方程
//辗转相除法 求最大公约数
ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a % b);
}
//Stein算法 求最大公约数
int SteinGCD(int a, int b) {
	if (a < b) {
		int t = a;
		a = b;
		b = t;
	}
	if (b == 0) return a;
	if ((a & 1) == 0 && (b & 1) == 0)
		return SteinGCD(a >> 1, b >> 1) << 1;
	else if ((a & 1) == 0 && (b & 1) != 0)
		return SteinGCD(a >> 1, b);
	else if ((a & 1) != 0 && (b & 1) == 0)
		return SteinGCD(a, b >> 1);
	else
		return SteinGCD(a - b, b);
}
//求解ax+by=gcd(a, b)
//返回值为gcd(a, b)
ll extgcd(ll a, ll b, ll& x, ll& y) {

	ll d = a;
	if(b) {
		d = extgcd(b, a % b, y, x);
		y -= (a / b) * x;
	} else x = 1, y = 0;
	return d;
}
//求解a关于模上m的逆元
//返回-1表示逆元不存在
ll mod_inverse(ll a, ll m) {

	ll x, y;
	ll d = extgcd(a, m, x, y);
	return d == 1 ? (m + x % m) % m : -1;
}
//快速幂费马小定理求逆元
ll mod_inverse2(ll a, ll m) { //m是素数,a的逆元就是a的m-2次方
	return qpow(a, m - 2, m);
}
/****************
逆元不存在,求解 a / b mod k(前提:b | a)
逆元存在时,a / b mod k 等价于a * B mod k(B是b模上k的逆元)
但是逆元不存在时:通用公式:a / b mod k = a mod(k * b) / b
---------------------------------------------
费马小定理和扩展欧几里得算法求逆元是有局限性的,
它们都会要求a和m互素(此处的a和m是之前ax = 1(mod m)中的a和m,
在这里应该是这里的b和m互素
****************/
//线性求逆元
int inv[10010];   //从1到n的逆元
void init(int n) {
	inv[1] = 1;
	for (int i = 2; i <= n; ++i)
		inv[i] = (long long)(p - p / i) * inv[p % i] % p;
}
//线性求任意 n 个数的逆元
int a[10010];    // 要求的n个数
int s[10010];    // 前缀积
int inv1[10010]; // 第i个数的逆元
void init1(int n,int p) {
	s[0] = 1;
	for (int i = 1; i <= n; ++i) s[i] = s[i - 1] * a[i] % p;
	long long sv[n] = mod_inverse(s[n], p);
	for (int i = n; i >= 1; --i) {
		inv[i] = svn * s[i - 1] % p;
		svn = svn * a[i] % p;
	}
}
//中国剩余定理  -->  除数两两互质
ll china(ll a[], ll m[], int n) {//a数组是余数,m数组是两两互质的数字

	ll M = 1, ans = 0;
	for(int i = 0; i < n; i++)M *= m[i];
	for(int i = 0; i < n; i++) {
		ll mi = M / m[i], x, y;
		extgcd(mi, m[i], x, y);
		//求出mi模上m[i]的逆元x  mi * x + m[i] * y = gcd(mi, m[i]) = 1(两两互质)
		ans = ans + ((a[i] % M) * (mi % M) % M) * (x % M) % M;
		ans = (ans % M + M) % M;
	}
	return ans;
}
//扩展_中国剩余定理  -->  除数两两不一定互质
ll ex_china(ll a[], ll m[], int n) {//a数组是余数,m数组是除数

	ll m0 = m[0], a0 = a[0];
	for(int i = 1; i < n; i++) {
		ll x, y;
		ll g = extgcd(m0, m[i], x, y);//求出m0 * x + m[i] * y = gcd(x, y)
		ll c = (a[i] - a0 % m[i] + m[i]) %m [i];
		if(c % g)return -1;
		x = mul(x , c / g , m[i] / g);
		//求出m0 * x + m[i] * y = a[i] - a0的解x
		//此处模上m[i]是为了取绝对值最小的一个x,因为x的通解就是x+k*m[i]
		a0 = x * m0 + a0;     //代回原式,求出最大的K
		m0 = m0 / g * m[i];     //m0更新为m0和m[i]的lcm
		a0 = ((a0 % m0) + m0) % m0;
	}
	return a0;
}
//< 4 > 组合数学
/************************************
n和m较大,但是p为素数的时候
Lucas定理是用来求 c(n,m) mod p,p为素数的值。
C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
也就是Lucas(n,m)%p=Lucas(n/p,m/p)*C(n%p,m%p)%p
***********************************/
//1, P较大,不打表:
ll C(ll n, ll m, ll p) { //组合数C(n, m) % p
	if(m > n)return 0;
	ll up = 1, down = 1;//分子分母;
	for(int i = n - m + 1; i <= n; i++)up = up * i % p;
	for(int i = 1; i <= m; i++)down = down * i % p;
	return up * mod_inverse(down, p) % p;
}
ll Lucas(ll n, ll m, ll p) {
	if(m == 0)return 1;
	return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
//-----------------------------------------------------------
//2, P较小,打表:
const int maxn = 1e5 + 10;
ll fac[maxn];//阶乘打表
void init(ll p) {//此处的p应该小于1e5,这样Lucas定理才适用
	fac[0] = 1;
	for(int i = 1; i <= p; i++)
		fac[i] = fac[i - 1] * i % p;
}
//组合数C(n, m) % p
ll C(ll n, ll m, ll p) {
	if(m > n)return 0;
	return fac[n] * mod_inverse(fac[m] * fac[n - m], p) % p;
}
//卢卡斯定理
ll Lucas(ll n, ll m, ll p) {
	if(m == 0)return 1;
	return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
//计算n! mod pk的部分值  pk为pi的ki次方
ll Mul(ll n, ll pi, ll pk) {
//算出的答案不包括pi的幂的那一部分
	if(!n)return 1;
	ll ans = 1;
	if(n / pk) {
		for(ll i = 2; i <= pk; i++) //求出循环节乘积
			if(i % pi)ans = ans * i % pk;
		ans = qpow(ans, n / pk, pk); //循环节次数为n / pk
	}
	for(ll i = 2; i <= n % pk; i++)
		if(i % pi)ans = ans * i % pk;
	return ans * Mul(n / pi, pi, pk) % pk;//递归求解
}

//计算组合数C(n, m) mod pk的值 pk为pi的ki次方
ll C(ll n, ll m, ll p, ll pi, ll pk) {
	if(m > n)return 0;
	ll a = Mul(n, pi, pk), b = Mul(m, pi, pk), c = Mul(n - m, pi, pk);
	ll k = 0, ans;//k为pi的幂值
	for(ll i = n; i; i /= pi)k += i / pi;
	for(ll i = m; i; i /= pi)k -= i / pi;
	for(ll i = n - m; i; i /= pi)k -= i / pi;
	ans = a * mod_inverse(b, pk) % pk * mod_inverse(c, pk) % pk * pow(pi, k, pk) % pk;//ans就是n! mod pk的值
	ans = ans * (p / pk) % p * mod_inverse(p / pk, pk) % p;//此时用剩余定理合并解
	return ans;
}
//exLucas定理是用来求 c(n,m) mod p,p不为素数的值。
ll exLucas(ll n, ll m, ll p) {
	ll x = p;
	ll ans = 0;
	for(ll i = 2; i <= p; i++) {
		if(x % i == 0) {
			ll pk = 1;
			while(x % i == 0)pk *= i, x /= i;
			ans = (ans + C(n, m, p, i, pk)) % p;
		}
	}
	return ans;
}
//卡特兰数
/*   应用
     1.n个数进栈,有h(n)种出栈方式;
     2.凸n边形,用多条不相交的对角线分成三角形,有h(n-2)种可能性;
     3.n个节点,有h(n)种不同的二叉搜索树
     4.给n对括号排序,有h(n)种不同的正确的排序方式
     5.买票找零n个50元,m个100元(一开始柜台没零钱)
     6.n*n棋盘从左下角走到右上角而不穿过主对角线的走法
     7.矩阵连乘的括号化
     8.在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数
     9.n层阶梯矩阵切割成n个长度递增矩阵的切割法
*/
/*
递推关系:  h(n)=h(n-1)*(4*n-2)/(n+1);

通项公式:  h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
            h(n)=C(2n,n)-C(2n,n-1)(n=0,1,2,...)

进出不同(左右括号数不同)时:  h(n,m)=C(n+m,n)-C(n+m,n+1)
(n代表必须先有的项数量,n>m,如左括号,入栈)
*/
const int mod = 1e9 + 7;
ll inv(ll a) {
	return qpow(a,mod-2);
}
ll fac[N * 3];
void init_fac() {
	fac[0] = fac[1] = 1ll;
	for(int i = 2; i <= 2 * N; i++)
		fac[i] = fac[i - 1] * i % mod;
}
ll C(ll a,ll b) { //组合数
	if(b > a || b < 0) return 0;
	return fac[a] * inv(fac[b]) % mod * inv(fac[a - b]) % mod;
}
//公式法
ll catalan(ll n) {
	return (C(2 * n, n) - C(2 * n, n - 1) + mod) % mod;
}
ll catalan(ll n,ll m) { //m为大者
	return (C(n + m, n) - C(n + m, n + 1) + mod) %mod;
}
//约瑟夫环
//f(n,m,k)  -->  
//n个人围成约瑟夫环,数到第k个数自杀,第m个死亡的人编号  
//时间复杂度:O(m) 
ll f(ll n,ll m,ll k){
	if(m==1)return (k-1)%n;
	return (f(n-1,m-1,k)+k)%n;
}
int main()
{   
    int t,cs=1;
    scanf("%d",&t);
    while (t--){
    	ll ans=0; 
        scanf("%I64d%I64d%I64d",&n,&m,&k);
        printf("Case #%d: ",cs++);
        
        if(k==1)printf("%I64d\n",m);
        //f(n,m,k)求得的是编号0~n-1时的编号 
        else if(m<=1e6)printf("%I64d\n",f(n,m,k)+1);
        //变加法为乘法,省略掉后面x个人(自杀直到这一圈的结尾)的一次次加法 
        //时间复杂度:O(应该能过) 
        else {
        	ll cc=n-m+1;
        	ll ans=(k-1)%cc;
        	ll num=1;
        	while(num<m){
        		//如果下一个自杀的人就是下一圈 
        		if(ans+k>=cc+1){
        			cc++;
        			ans=(ans+k)%cc;
        			num++;
				}else {
					ll x=(cc-ans-1)/(k-1);
					//x --> 当前圈可以 继续自杀多少人 
					x=min(x,m-num);
					ans=ans+x*k;
					num+=x;
					cc=cc+x; 
				}
			}
			printf("%I64d\n",ans+1);
		}
    }
    return 0;
} 
//康托展开 && 逆康托展开
static const int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};   // 阶乘
int cantor(int *a, int n) {
	int x = 0;
	for (int i = 0; i < n; ++i) {
		int smaller = 0;  // 在当前位之后小于其的个数
		for (int j = i + 1; j < n; ++j) {
			if (a[j] < a[i])
				smaller++;
		}
		x += FAC[n - i - 1] * smaller; // 康托展开累加
	}
	return x;  // 康托展开值
}
void decantor(int x, int n) {
	vector <int> v;  // 存放当前可选数
	vector <int> a;  // 所求排列组合
	for(int i = 1; i <= n; i++)
		v.push_back(i);
	for(int i = m; i >= 1; i--) {
		int r = x % FAC[i - 1];
		int t = x / FAC[i - 1];
		x = r;
		sort(v.begin(), v.end());// 从小到大排序
		a.push_back(v[t]);      // 剩余数里第t+1个数为当前位
		v.erase(v.begin() + t);   // 移除选做当前位的数
	}
}

//< 5 > 原根 && 离散对数
//大步小步算法 --> 求解a^x ≡b(mod n) 模数p不为素数
ll ext_log_mod(ll a, ll b, ll n) {
	if(b >= n)return -1;//一些特殊情况的判断
	a %= n;
	if(b == 1)return 0;
	//if(n == 1)return -1;
	ll cnt = 0;//记录消因子次数
	ll tmp = 1;//存当前a'的值
	for(ll g = __gcd(a, n); g != 1; g = __gcd(a, n)) {
		if(b % g)return -1;//不能整除

		b /= g;  n /= g;
		tmp = tmp * a / g % n;
		cnt++;
		if(b == tmp)return cnt;
	}

	ll m = sqrt(n + 0.5);
	ll t = b;
	map<ll, ll>Map;//记录b * a ^ i, i
	Map[b] = 0;
	for(int i = 1; i <= m; i++) {
		b = b * a % n;
		Map[b] = i;
	}
	a = qpow(a, m, n);
	for(int k = 1; k <= m; k++) { //枚举k
		tmp = tmp * a % n;//求出tmp*a^(k*m)
		if(Map.count(tmp))return k * m - Map[tmp] + cnt;
	}
	return -1;
}
int tot;//素因子个数
int a[100005];
//质因数分解n
void get_fact(ll n) {
	tot = 0;
	for(ll i = 2; i * i <= n; i++) {
		if(n % i == 0) {
			a[tot++] = i;
			while(n % i == 0)n /= i;
		}
	}
	if(n != 1)a[tot++] = n;
}
//测试g是不是p的原根 此处p是素数 欧拉函数值为p - 1
bool g_test(ll g, ll p, ll ou) {
	for(ll i = 0; i < tot; i++) {
		if(pow(g, ou / a[i], p) == 1)return false;
	}
	return true;
}
//求解p最小原根,本题p为素数//返回最小的原根
int proot(ll p) {
	ll ou = euler_phi(p);
	get_fact(ou);//素数的欧拉函数值为p - 1
	int g = 1;
	while(1) {
		if(g_test(g, p, ou))return g;
		g++;
	}
}
//若gcd(a,m)=1,使得a^l = 1(mod m)的最小l值
//直接对euler(m)求出因子即可,从小到大依次判断是不是符合a^d = 1(mod m)
ll ord_mod(ll a, ll m) {
	ll ans = 0;
	ll ou = euler_phi(m);
	for(int i=1; i <= sqrt(ou); i++) {
		if(n / i == 0) {
			if(qpow(a, i, m) == 1) {
				ans = i;
				break;
			}
			if(qpow(a, n/i, m) == 1) {
				ans = min(ans, n/i);
			}
		}
	}
}
//< 6 > 线性代数
//矩阵快速幂
const int mod = 1e9+7;
struct pl {
	ll a[15][15];
} p,pp;

//矩阵乘法
pl work(pl work,pl y) {         //矩阵乘法
	pl box;
	memset(box.a,0,sizeof(box.a));
	for(int i=1; i<=3; i++) {
		for(int k=1; k<=3; k++) {
			if(work.a[i][k])
				for(int j=1; j<=3; j++) {
					box.a[i][j]=(box.a[i][j]+(work.a[i][k]*y.a[k][j])%mod)%mod;
				}
		}
	}
	return box;
}

//矩阵快速幂
pl fastpow(ll kk) {           //快速幂
	pl ans;
	memset(ans.a,0,sizeof(ans.a));
	for(int i=1; i<=3; i++) ans.a[i][i]=1;
	while(kk) {
		if(kk&1) ans=work(ans,p);
		kk>>=1;
		p=work(p,p);
	}
	return ans;
}
//高斯消元法 求 多元一次方程组
const double EPS=1e-8;
#define maxn 105
double A[maxn][maxn];    //x的系数行列式
double B[maxn][maxn+1];  //A + b
double x[maxn];          //ans
double b[maxn];          //方程组等号右侧
int n;
//求解Ax=b,其中A是方阵
void gauss_jordan() {
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < n; j++) {
			B[i][j] = A[i][j];
		}
	}
	for(int i = 0; i < n; i++) {
		B[i][n] = b[i];
	}
	for(int i = 0; i < n; i++) {
		//把正在处理的未知数系数的绝对值最大的式子换到第i行
		int pivot = i;
		for(int j = i; j < n; j++) {
			if(abs(B[j][i] > abs(B[pivot][i]))) pivot = j;
		}
		for(int j = 0; j <= n; j++) {
			swap(B[i][j], B[pivot][j]);
		}
		//无解或者无穷多解
		if(abs(B[i][i]) < EPS) return;
		//把正在处理的未知数的系数变成1
		for(int j = i + 1; j <= n; j++) {
			B[i][j] /= B[i][i];
		}
		for(int j = 0; j < n; j++) {
			if(i != j) {
				//从第j个式子中消去第i个未知数
				for(int k = i + 1; k <= n; k++) {
					B[j][k] -= B[j][i] * B[i][k];
				}
			}
		}
	}
	for(int i = 0; i < n; i++) {
		x[i] = B[i][n];
	}
}
//异或 线性基
struct Linear_Basis {
	ll b[63],nb[63],tot;
	void init() {   //初始化
		tot=0;
		memset(b,0,sizeof(b));
		memset(nb,0,sizeof(nb));
	}
	bool ins(ll x) {   //插入数字
		for(int i=62; i>=0; i--)
			if (x&(1LL<<i)) {
				if (!b[i]) {
					b[i]=x;
					break;
				}
				x^=b[i];
			}
		return x>0;
	}
	ll Max(ll x) {    //求最大值
		ll res=x;
		for(int i=62; i>=0; i--)
			res=max(res,res^b[i]);
		return res;
	}
	ll Min(ll x) {    //求最小值
		ll res=x;
		for(int i=0; i<=62; i++)
			if (b[i]) res^=b[i];
		return res;
	}
	void rebuild() {  //将线性基改造成每一位相互独立
		for(int i=62; i>=0; i--)
			for(int j=i-1; j>=0; j--)
				if (b[i]&(1LL<<j)) b[i]^=b[j];
		for(int i=0; i<=62; i++)
			if (b[i]) nb[tot++]=b[i];
	}
	ll Kth_Max(ll k) {  //第k大值
		ll res=0;
		for(int i=62; i>=0; i--)
			if (k&(1LL<<i)) res^=nb[i];
		return res;
	}

} LB;
L_B merge(const L_B &n1,const L_B &n2) {   //线性基合并
	L_B ret = n1;
	for (int i = 60; i >= 0; i--)
		if (n2.d[i])
			ret.insert(n1.d[i]);
	return ret;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值