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)
然后记得用高精度。
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;
}