在这片梦想之地,不堪回首的过去像泡沫一样散去,|

PassName

园龄:3年1个月粉丝:32关注:16

2023.11.3 做题记录

AcWing.97 约数之和

题目传送门

约数个数定理

对一个大于1的整数nn可以分解质因数为i=1kpiai=p1a1·p2a2···pkak

则n的正约数的个数就是f(n)=i=1kai+1=(a1+1)(a2+1)···(ak+1),这个很好证明,因为p1a1的约数有p10,p11,p12p1a1,共(a1+1)个,同理pkak的约数有(ak+1)

约数定理

n(a1+1)(a2+1)···(ak+1)个正约数的和为:
(p10+p11++p1a1)(p20+p21+p2a2)(pk0+pk1+pkak)

对于这题来说,根据约数定理就有AB的约数和为:
(1+p11++p1Ba1)(1+p21+p2Ba2)(1+pk1+pkBak)

定义calc(n,k)p0+p1++pk,当 k 为偶数,分成两部分的和变为(p0++pk2)+(pk2+1+pk)

后面的多项式提取pk2+1,变成(p0++pk2)+pk2+1(p0+pk2)

将两项合并(1+pk2+1)(p0++pk2),这个式子可以转化为(1+pk2)calc(p,k2)

k 为奇数时。即 calc(p,k1)+pk1

#include<bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int mod = 9901;
int a, b;
int ans = 1;

//保存质因子以及出现的次数
unordered_map<int, int> primes;

void divide(int n) 
{
    for(int i = 2; i <= n / i; i++) 
	{
        if(n % i == 0) 
		{
            while(n % i == 0) 
			{
                primes[i]++;
                n /= i;
            }
        }
    }
    if(n > 1) 
	{
        primes[n]++;
    }
}

int qpow(int a, int b)
{
	int res = 1;
	while(b)
	{
		if (b & 1) res = res * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}

int calc(int p, int k) 
{
    if(k == 1) return 1;  
    if(k % 2 == 0) 
	{  
        return (qpow(p, k / 2) + 1) * calc(p, k / 2) % mod;
    }
    return (qpow(p, k - 1) + calc(p, k - 1)) % mod;
}

signed main()
{
    cin >> a >> b;

    divide(a);

    for(auto i : primes) 
	{
        int p = i.first;
		int k = i.second * b;
        ans = ans * calc(p, k + 1) % mod;
    }
    
    if (a == 0)
    {
        cout << 0 << endl;
        return 0;
    }
    
    cout << ans << endl;

    return 0;
}

[HNOI2003] 激光炸弹

题目传送门

二维前缀和即可:

f[i][j]=f[i1][j]+f[i][j1]f[i1][j1]+a[i][j]

细节见代码:

#include <bits/stdc++.h>

#define rint register int
#define endl '\n'

using namespace std;

const int N = 5e3 + 5;

int s[N][N];
int n, m;
int max_x, max_y;
int ans;

signed main()
{
    cin >> n >> m;
    
    max_x = max_y = m;
    
    for (rint i = 1; i <= n; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        x++, y++;
        s[x][y] += z;
        //如果不是 += z,可能出现重标记情况
        //洛谷数据太水,s[x][y] = z 也能过
        max_x = max(max_x, x);
        max_y = max(max_y, y);
        //初始化
        //二维前缀和不能便输入边存答案
    }
    
    for (rint i = 1; i <= max_x; i++)
    {
        for (rint j = 1; j <= max_y; j++)
        {
            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + s[i][j];			
		}		
	}
            
    for (rint i = m; i <= max_x; i++)
    {
        for (rint j = m; j <= max_y; j++)
        {
            ans = max(ans, s[i][j] - s[i][j - m] - s[i - m][j] + s[i - m][j - m]);				
		}
	}
 
    cout << ans << endl;
    
    return 0;
}

Acwing.128 文本编译器

题目传送门
开两个栈即可:

    1. I x:把 x 插入栈 A,更新栈 A 的栈顶位置的前缀和,更新栈 A 的栈顶位置的最大前缀和
    1. D:弹出栈 A 的栈顶元素
    1. L:弹出栈 A 的栈顶元素并插入栈 B
    1. R:弹出栈 B 的栈顶元素并插入栈 A 中,更新栈 A 的栈顶位置的前缀和,更新栈 A 的栈顶位置的最大前缀和
    1. Q k:直接返回 f[k]

SP4354 雪花

题目传送门

暴力 hash 即可

但是从每一个角都存一遍显然会寄,所以考虑对整个序列求和求积,然后对一个大质数取模得到 hash 值,存储上可以采用邻接表。

本文作者:PassName

本文链接:https://www.cnblogs.com/spaceswalker/p/17807662.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   PassName  阅读(11)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起