4.4日刷题记录

斐波那契前 n 项和

构造: f[1] * A^(n - 1) = f[n] ,它们都是矩阵

int n, m;

void mul(int a[], int b[], int c[][3]){
    int temp[3] = {0};

    for(int i = 0; i < 3; ++i){
        for (int j = 0; j < 3; ++j){
            temp[i] = (temp[i] + (ll)b[j] * c[j][i]) % m;
        }
    }
    memcpy(a, temp, sizeof(temp));
}

void mul(int a[][3], int b[][3], int c[][3]){
    int temp[3][3] = {0};
    for (int i = 0; i < 3; ++i){//3*3矩阵
        for (int j = 0; j < 3; ++j){
            for (int k = 0; k < 3; ++k){
                temp[i][j] = (temp[i][j] + (ll)a[i][k] * b[k][j]) % m;
            }
        }
    }
    memcpy(c, temp, sizeof(temp));
}

int main() {
	IOS;
	// freopen("P1908_6.in","r",stdin);//读入数据
	// freopen("P1908.out","w",stdout); //输出数据
	cin >> n >> m;
    int f[3][3] = {
        {0, 1, 0},
        {1, 1, 1},
        {0, 0, 1}//!!!核心矩阵的构造
    };
    int a[3] = {1, 1, 1};

    --n;
    while(n){
        if(n & 1)
            mul(a, a, f);// res = res * a
        mul(f, f, f); // a = a * a
        n >>= 1;
    }

    cout << a[2];
    return 0;
}

斐波那契计算公式
精度不高 + n不能太大

int Fibonacci(int n) {
        double sqrt5 = sqrt(5);
        double alpha = (1 + sqrt5) / 2;
        double beta = (1 - sqrt5) / 2;
        double ret = (pow(alpha, n) - pow(beta, n)) / sqrt5;
        return (int) ret;
    }

快速幂板子

using namespace std;
typedef long long ll;

ll fast_power(ll a, ll b, ll p){
    ll pr = 1;
    while(b > 0){
        if(b & 1)
            pr = pr * a % p;
        a = a * a % p;
        b >>= 1;
    }
}

int main(){
    ll a, b, p;
    if(b == 0)
        ll ans = 1 % p;
    return 0;
}

y总矩阵快速幂板子

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <ctime>

using namespace std;

const int MOD = 1000000007;

void mul(int a[][2], int b[][2], int c[][2])
{
    int temp[][2] = {{0, 0}, {0, 0}};
    for (int i = 0; i < 2; i ++ )
        for (int j = 0; j < 2; j ++ )
            for (int k = 0; k < 2; k ++ )
            {
                long long x = temp[i][j] + (long long)a[i][k] * b[k][j];
                temp[i][j] = x % MOD;
            }
    for (int i = 0; i < 2; i ++ )
        for (int j = 0; j < 2; j ++ )
            c[i][j] = temp[i][j];
}


int f_final(long long n)
{
    int x[2] = {1, 1};

    int res[][2] = {{1, 0}, {0, 1}};
    int t[][2] = {{1, 1}, {1, 0}};
    long long k = n - 1;
    while (k)
    {
        if (k&1) mul(res, t, res);
        mul(t, t, t);
        k >>= 1;
    }

    int c[2] = {0, 0};
    for (int i = 0; i < 2; i ++ )
        for (int j = 0; j < 2; j ++ )
        {
            long long r = c[i] + (long long)x[j] * res[j][i];
            c[i] = r % MOD;
        }

    return c[0];
}


int main()
{
    long long n ;

    cin >> n;
    cout << f_final(n) << endl;

    return 0;
}

作者:yxc
链接:https://www.acwing.com/blog/content/25/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

包子凑数

这道题,听了几遍哈,模模糊糊懂了,但要再给我一模一样的题哈,还是不会(后面,裴蜀定理)
几个结论:
1.两个数不能凑出的最大的数是(a - 1) * (b - 1) -1, 而n个数的gcd为不为1时,有无穷个数凑不出来
2.如果a,b有gcd,那么一定存在ax + by = gcd(a, b),或者说gcd = 1,一定可以凑出ax + by = 1,(x, y是可以为负数的,因为这个数足够大,就能利用a*(x - d) + b*(y + d)这样配凑)

int n, m;
    cin >> n;
    int d = 0;
    for (int i = 0; i < n; ++i){
        cin >> a[i];
        d = __gcd(d, a[i]);//范围在逐渐缩小,上界必定是一个不大的值
    }
    if(d != 1){
        cout << "INF";
        return 0;
    }
    f[0] = true;
    for (int i = 0; i < n; ++i){
        for (int j = a[i]; j < 10000; ++j){
            f[j] |= f[j - a[i]];
        }
    }
    int ans = 0;
    for (int i = 0; i < 10000; ++i){
        if(!f[i])
            ++ans;
    }
    cout << ans;

括号配对

…dp简直不是我这个年龄段该承受的东西,怎么还是二懂二懂啊呜
和密码脱落类似,在4.2号的记录里

int a[1005], f[105][105];

bool check(char a, char b){
    if(a == '(' && b == ')')
        return true;
    if(a == '[' && b == ']')
        return true;
    return false;
}

int main() {
	IOS;
	// freopen("P1908_6.in","r",stdin);//读入数据
	// freopen("P1908.out","w",stdout); //输出数据
	string s;
    cin >> s;
    int len = s.size();
    for (int i = 0; i < len; ++i)
        f[i][i] = 1;
        for (int k = 2; k <= len; ++k)
        {
            for (int i = 0; i + k - 1 < len; ++i)
            {
                int j = i + k - 1;
                f[i][j] = mod;//f[][]被用上的,就是不能被匹配的
                if (check(s[i], s[j]))
                    f[i][j] = f[i + 1][j - 1];
                if (j >= 1)//左
                    f[i][j] = min(f[i][j], min(f[i + 1][j], f[i][j - 1]) + 1);

                for (int z = i; z < j; ++z)//右
                    f[i][j] = min(f[i][j], f[i][z] + f[z + 1][j]);
            //划分区间长度,取之间最小的
            //是按括号来的,iz和z+1j完全独立,所以可以取+
            //左右两边同时取最小
            }
        }
        cout << f[0][len - 1];
        return 0;
}

五指山

在这里插入图片描述

裴蜀定理
裴蜀定理证明式子
裴蜀定理

0和任何数的公约数都等于另一个数

ll exgcd(ll a, ll b, ll &x, ll &y){
	if(!b){
		x = 1, y = 0;
		return a;
	}
	ll d = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return d;
}

int main() {
	IOS;
	// freopen("P1908_6.in","r",stdin);//读入数据
	// freopen("P1908.out","w",stdout); //输出数据
	int t;
	cin >> t;
	while(t--){
		ll n, d, x, y;
		ll a, b;
		cin >> n >> d >> x >> y;
		ll gcd = exgcd(n, d, a, b);
		if((x - y) % gcd != 0)
			cout << "Impossible" << endl;
		else {
			//同时扩大
			n /= gcd;
			b *= (y - x) / gcd;//倍数
			cout << (b % n + n) % n << endl;
		}
	}
	return 0;
}

日志统计

int cnt[maxn];
bool st[maxn];
pair<int, int> p[maxn];

int main() {
	IOS;
	// freopen("P1908_6.in","r",stdin);//读入数据
	// freopen("P1908.out","w",stdout); //输出数据
	int n, d, k;
	cin >> n >> d >> k;
	for (int i = 0; i < n; ++i){
		cin >> p[i].first >> p[i].second;
	}
	sort(p, p + n);
	int j = 0;
	for (int i = 0; i < n; ++i){//枚举时间点
		int id = p[i].second;
		++cnt[id];

		while(p[i].first - p[j].first >= d){//j = l, i = r
			--cnt[p[j].second];//j是开头下一个还在d外的
			++j;
		}

		if(cnt[id] >= k)
			st[id] = true;
	}
	for (int i = 0; i <= 100000; ++i){
		if(st[i])
			cout << i << endl;
	}
		return 0;
}

有重复的意味着可以优化,找不同点

总结

今天好像学了很多东西,又好像根本没学。
人给我冷麻了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值