【数学】 一些的数学题

Uva 11401 Counting triangles

大意: 给一个n,问从边长为1,2,3...........n 中能够组成几个三角形。

分析:1.n<=3 肯定不行

          2.换个思路,令f(x)表示从1.....x中必须取x能够组成三角形的个数, s(x) 表示所有情况。易得s(x) = s(x-1) + f(x)。因此我们接下来只要考虑f(x)怎么求即可。

          3.当n奇数,比如n=9 —— [1,2,3,4,·5·,6,7,8,\9],假设我们先取打后取小,5是分界点,也就是从5以前的数都是不可以取的,因为即使4 + 5 也不大于9。 然而5,6,7,8这4个数可以任取2个C(4,2)。

            然后对于5之前的数,5有0种,6有一种,7有2种,8有三种。是个等差数列求和问题。

         4. 当n偶数 , 比如n=8 ——[1,2,3,·4·,5,6,7,\8] 同样的道理,可以拆解成一个等差数列+一个组合

#include <bits/stdc++.h>
using namespace std;
typedef long long long_int;
long_int n = 0;
long_int F[1000010];

long_int solve(long_int n){
	long_int ans = 0;
	long_int k = (n-1) / 2;
	ans += k*(k-1) / 2;
	if(n&1){
		ans += k*(k-1)/2;
	} else {
		ans += k*(k+1)/2;
	}
	return ans;
}

int main(){
	for (int i = 4 ; i <= 1000000 ; ++i)
		F[i] = F[i-1] + solve(i);
	while(cin >> n){
		if(n < 3) break;
		cout << F[n] << endl;
	}
	return 0;
}

eoj 3506 : 玄学 19260817


EOJ 3428. EvenOdd

https://acm.ecnu.edu.cn/problem/3428/

无法预处理,范围过大

求的时候有区间性质:[L,R] 可以由 [L/2,R/2] 解得到

然后预处理一段,比如1~10^6,然后类似于线段树处理,分为范围全在里面,全不在里面,有重叠三种情况

考虑复杂度 f(n) = f(n/2) + O(1) 时间O(lgN) , 对于 N = 10^18

切记你的递归里必须只允许递归掉用本身一次 , 两次则退化为O(N)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int maxl = 1e5;
const ll mods = 1000000007;

ll f[maxn];
ll sum[maxn];
ll func(ll x)
{
	int it = 0;
	while(x > maxl)
	{
		if(x%2) x++;
		else x/= 2;
		it++;
	}
	int index = (int)x;
	return (f[index] + it) % mods;
} 

void init()
{
	f[1] = 0;
	f[2] = 1;
	for (int i = 3 ; i <= maxl ; ++i)
	{
		if(i%2)
			f[i] = f[(i+1)/2] + 2;
		else
			f[i] = f[i/2] + 1;		
		f[i] %= mods;	
	} 
	for (int i = 1 ; i <= maxl ; ++i){
		sum[i] = f[i] + sum[i-1];
		sum[i] %= mods;	
	}
}

inline ll query(ll L, ll R)
{
	return (sum[R] - sum[L-1]) % mods;
}

ll getAns(ll L, ll R)
{
	if(L == R) return func(L);
	if(L <= maxl && R <= maxl)
		return query(L,R);
	if(L <= maxl && R > maxl)
	{
		ll sum = 0;
		sum += query(L,maxl);
		sum += getAns(maxl+1,R);
		sum %= mods;
		return sum;
	}
	else
	{
		ll sum = 0;
		if(L%2) sum += func(L++);
		if(R%2) sum += func(R--);
		ll range = R/2 - L/2 + 1;
		sum = sum % mods;
		sum += getAns(L/2,R/2)*2 + 3*range - 2 - func(L/2);
		sum %= mods;
		return sum;
		

	}
}


int main()
{
	init();
	ll x = 0, y = 0;
	while(cin >> x >> y){cout << getAns(x,y) << endl;}
	
	return 0;
}


EOJ 3205. Prime Gap

https://acm.ecnu.edu.cn/problem/3205/

我不知道那么水的题居然没人做,线性筛+二分。

#include <bits/stdc++.h>
#define maxn 1300000
#define maxp 200000
#define maxL 100000
using namespace std;
bool isPrime[maxn];
int ans[maxp];
int tot = 0;
void getPrime(int n){
	for (int i = 0 ; i < maxn; ++i) isPrime[i] = true;
	for (int i = 2 ; i <= n ; ++i){
		if(isPrime[i])
			ans[++tot] = i;
		for (int j = 1 ; (j <= tot) &&  i*ans[j] <= n ; ++j)
		{
			isPrime[i*ans[j]] = false;
			if(i%ans[j] == 0) break;
		}
	}
}

int binary_search(const int k){
	int l = 1, r = maxL, mid = 0;
	while(l <= r)
	{
		mid = (l+r) >> 1;
		if(ans[mid] < k && k < ans[mid + 1])
			return mid;
		else if(ans[mid] > k)  r = mid - 1;
		else l = mid + 1;
	}
	return -1;
}

int main(){
	getPrime(maxn);
	int num = 0;
	while(scanf("%d",&num) && num)
	{
		if(isPrime[num])
			printf("0\n");
		else
		{
			int k = binary_search(num);
			printf("%d\n",ans[k+1] - ans[k]);
		}
	}
	return 0;
}

EOJ 3203. The Balance

https://acm.ecnu.edu.cn/problem/3203/

因为称的东西是可以再随便什么地方的。所以其实是接一个ax + by = c (mod n) 的题目,扩展欧几里得

然后对x,对y的得到的解是可能会不一样,比较取个小。

#include <bits/stdc++.h>
using namespace std;
typedef long long long_int;
long_int gcd(long_int a,long_int b){
	if(b == 0) return a;
	else return gcd(b,a%b); 
}
long_int extend_gcd(long_int a, long_int b, long_int& x, long_int& y)
{
	if(b == 0)
	{
		x = 1; y = 0;
		return a;	
	}
	else
	{
		long_int r = extend_gcd(b,a%b,y,x);
		y -= x * (a/b);
		return r;	
	}
}



int main()  
{  
    long long m,n,k;  
    while(cin>>m>>n>>k && m + n + k)  
    {  
        long long g = gcd(m,n);  
        long long x,y;  
        long long vy,vx;  
        m /= g;  
        n /= g;  
        extend_gcd(m,n,x,y);  
        vx = x * k / g; 
        vx = (vx % n + n) % n;  
        vy = (k / g - m * vx) / n;  
        if(vy < 0) vy = -vy;  
          
        y = y * k / g;    
        y = (y % m + m) % m;  
        x = (k / g - n * y) / m;  
        if(x < 0) x = -x;  
        if(x + y > vx + vy)  
        {  
            x = vx;  
            y = vy;  
        }  
        cout<<x<<" "<<y<<endl;  
    }  
    return 0;     
}   

EOJ 5. 特殊的子集

https://acm.ecnu.edu.cn/problem/5/

定义f(n) = 当集合为{1,2,3....n}的时候,特殊的子集按照题目所求的值。
S(n) 为所由能够由{1,2,3,4....n}产生的特殊的子集所构成的集合
1、考虑暴力法
利用生成排列,得到每一个非相邻子集,O(2^n)
2、考虑二进制优化,考虑个p;

3、分析非相邻子集的特点:
n = 1 : {1}
n = 2 : {1},{2}
n = 3 : {1},{2},{3}; {1,3}
n = 4 :{1}{2}{3}{4}; {1,3},{1,4}{2,4}
.....................................
观察发现:
1、对于每一个S(n),S(n-1) 总是它的子集。 换句话说,状态时没有后效性的,如果存在状态转移方程,那么就是可以使用dp的方法。
2、考虑不相邻的特性,显然的,我们发现:
对于任意属于S(n-2)的集合A,
{n} U A 总是可以构造成一个子集,
并且可以得出求值以后得到的值 = f(n-2) * n^2
3、从 (2) 我们可以得出所有含有 n 的非相邻集合的所有值。
此时S(n) 被分为两个集合: 1、包含n的集合 2、不包含n的集合
4、包含n的集合通过(2)算出
不包含n的集合的所有求值那就是S(n-1)的值,即f(n-1)
5、得出递推方程:
f(n) = f(n-1) + n^2f(n-2)
然后记得用高精度。

不给代码了,你们用python吧====


EOJ 1174. C Looooops

https://acm.ecnu.edu.cn/problem/1174/
问 for (variable = A; variable != B; variable += C) 是在k位计算机是否会中止
【注释:溢出等于 % (1<<k)】
也就是 x*C + A = y*B 是否有整数解
也就是 x*C + A = 0 (mod B) 是否有整数解,根据模方程的性质
也就是 xC = B-A (mod B)是否有整数解。 解一个模线性方程

千万要用1L << k

#include <bits/stdc++.h>
using namespace std;
typedef long long long_int;
long_int mod_num;
long_int A ,B,C,K;

long_int extend_gcd(long_int a, long_int b, long_int& x, long_int& y){
	if(b == 0){
		x = 1; y = 0;
		return a;
	} else {
		long_int r = extend_gcd(b,a%b,y,x);
		y -= x * (a/b);
		return r;
	}
}

long_int line_mod_equation(long_int a, long_int b, long_int n){
	long_int x = 0,y = 0;
	long_int d = extend_gcd(a,n,x,y);
	if(b % d) return -1;
	
	x = x*(b/d) % n;
	x = (x%(n/d) + n/d)%(n/d);
	return x;
}

int main(){
	while(1)
	{
	 	cin >> A >> B >> C >> K;
	 	if(A == 0 && B == 0 && C == 0 && K == 0) break;
	 	mod_num = 1L << K;
	 	long_int ans = line_mod_equation(C,(B-A+mod_num) % mod_num ,mod_num);
	 	if(ans == -1){
	 		cout << ("FOREVER") << endl; 
	 	}
		else {
		 	cout << ans << endl; 
		 }
	 }
	 return 0;
}


eoj 1499 & 2568

斐波那契数列用矩阵表示 + 快速幂

// 1499
#include <bits/stdc++.h> 
using namespace std;
typedef long long long_int;
const int maxn = 55;
const long_int mods = 1e8;
struct Matrix{
	int n,m;
	long_int a[maxn][maxn];
	void clear(){
		n = m = 0;
		memset(a,0,sizeof(a));
	} 
	Matrix operator + (const Matrix& b) const{
		Matrix tmp;
		tmp.clear();
		tmp.n = n;
		tmp.m = m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < n ; ++j)
				 tmp.a[i][j] = a[i][j] + b.a[i][j];
		return tmp;
	}
	Matrix operator - (const Matrix& b) const{
		Matrix tmp;
		tmp.clear();
		tmp.n = n;
		tmp.m = m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < n ; ++j)
				 tmp.a[i][j] = a[i][j] - b.a[i][j];
		return tmp;
	}
	
	Matrix operator * (const Matrix& b) const{
		Matrix tmp;
		tmp.clear(); 
		tmp.n = n;
		tmp.m = b.m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < b.m ; ++j)
				for (int k = 0 ; k < m ; ++k){
					 tmp.a[i][j] += a[i][k] * b.a[k][j];
					 tmp.a[i][j] %= mods;
				}
		return tmp;
	}
	
	Matrix& operator = (const Matrix& b) {
		n = b.n;
		m = b.m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < m ; ++j)
				 a[i][j] = b.a[i][j];
		return *this;
	}
	Matrix GetUnitMatrix(long_int k){
		Matrix tmp;
		tmp.clear();
		tmp.n = tmp.m = k;
		for (int i = 0 ; i < k ; ++i)
			tmp.a[i][i] = 1;
		return tmp; 
	}
	Matrix pow(int k){
		//assert(n == m);
		Matrix ans = GetUnitMatrix(n); 
		Matrix save = (*this);
	
		while(k)
		{
			if(k & 1) ans = ans * save;
			save = save * save;
			k >>= 1;
		}
		return ans;
	}	
	void PrintMatrix(){
		for (int i = 0 ; i < n ; ++i , cout << endl)
			for (int j = 0 ; j < m ; ++j)
				cout << a[i][j] <<' ';
	}
}; 

int F[5];
int main(){
    int start = 0;
	Matrix Fib;
	Fib.clear();
	Fib.n = Fib.m = 2;
	Fib.a[0][0] = 1;
	Fib.a[0][1] = 1;
	Fib.a[1][0] = 1;
	int p = 1;
	long_int k = 0;
	F[1] = 1;
	F[2] = 2;
	F[3] = 4; 
	while (cin >> k)
	{
		if (k <= 3)
		{
			cout << F[k];
			continue;
		}
		Matrix T = Fib.pow(k);
		cout << (T.a[0][1] + T.a[0][0] - 1) % mods << endl;
	}
	
	return 0;
	
}


#include <bits/stdc++.h> 
using namespace std;
const int maxn = 55;
const int mods = 1e4;
struct Matrix{
	int n,m;
	int a[maxn][maxn];
	void clear(){
		n = m = 0;
		memset(a,0,sizeof(a));
	} 
	Matrix operator + (const Matrix& b) const{
		Matrix tmp;
		tmp.clear();
		tmp.n = n;
		tmp.m = m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < n ; ++j)
				 tmp.a[i][j] = a[i][j] + b.a[i][j];
		return tmp;
	}
	Matrix operator - (const Matrix& b) const{
		Matrix tmp;
		tmp.clear();
		tmp.n = n;
		tmp.m = m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < n ; ++j)
				 tmp.a[i][j] = a[i][j] - b.a[i][j];
		return tmp;
	}
	
	Matrix operator * (const Matrix& b) const{
		Matrix tmp;
		tmp.clear(); 
		tmp.n = n;
		tmp.m = b.m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < b.m ; ++j)
				for (int k = 0 ; k < m ; ++k){
					 tmp.a[i][j] += a[i][k] * b.a[k][j];
					 tmp.a[i][j] %= mods;
				}
		return tmp;
	}
	
	Matrix& operator = (const Matrix& b) {
		n = b.n;
		m = b.m;
		for (int i = 0 ; i < n ; ++i)
			for (int j = 0 ; j < m ; ++j)
				 a[i][j] = b.a[i][j];
		return *this;
	}
	Matrix GetUnitMatrix(int k){
		Matrix tmp;
		tmp.clear();
		tmp.n = tmp.m = k;
		for (int i = 0 ; i < k ; ++i)
			tmp.a[i][i] = 1;
		return tmp; 
	}
	Matrix pow(int k){
		//assert(n == m);
		Matrix ans = GetUnitMatrix(n); 
		Matrix save = (*this);
	
		while(k)
		{
			if(k & 1) ans = ans * save;
			save = save * save;
			k >>= 1;
		}
		return ans;
	}	
	void PrintMatrix(){
		for (int i = 0 ; i < n ; ++i , cout << endl)
			for (int j = 0 ; j < m ; ++j)
				cout << a[i][j] <<' ';
	}
}; 

int main(){
    int start = 0;
	Matrix Fib;
	Fib.clear();
	Fib.n = Fib.m = 2;
	Fib.a[0][0] = 1;
	Fib.a[0][1] = 1;
	Fib.a[1][0] = 1;
	
	int k = 0;
	while (1)
	{
		if(start != 0) cout << endl;
		start ++; 
		cin >> k;
		if(k == -1) break;
		else if (k == 0)
		{
			cout << 0;
			continue;
		}
		Matrix T = Fib.pow(k);
		cout << T.a[0][1];
	}
	
	return 0;
	
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值