SDNU ACM-ICPC 2020 Freshman‘s first monthly competition(11-15)【解题报告】

前言

\quad 激动人心的新生月赛终于来了!经过一个多星期的比赛准备,这套题目呈现在大家面前。

\quad 为了尽量避免锅的出现,这次集结了 17,18,19 全部队员参与命题与验题工作,简直是 SDNU-ACM 有史以来最为浩大的工程(要是今天现场出锅就刺激了)。

\quad UPD:MD,今天还是出锅了。

说明

\quad 以下内容为现场赛时写的,一边看榜,一边写,所以是按照每道题被拿走FB的顺序写的。

题解

1616.Arithmetic Sequence[签到]

出题人:ymf \quad 验题人:lhr、wx、lzw

\quad 全场最简单的题目,于 00:02:572020Wangweiyi 拿走全场 First Blood

题目大意

\quad 给出一个整数 S S S,要求你构造一个长度最短的等差数列,使其和为 S S S.

分析

\quad 直接输出 S S S 不就好啦.

\quad 小坑点: m a x ( S ) = I N T _ M A X + 1 max(S) = INT\_MAX + 1 max(S)=INT_MAX+1,需要使用 l o n g    l o n g long\; long longlong 读入.

\quad 时间复杂度: O ( 1 ) O(1) O(1).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e5;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;

void work()
{
    ll s; scanf("%lld", &s);
    printf("%lld\n", s);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1625.星球大战1[思维 + 枚举]

出题人:lra \quad 验题人:lhr、lzw

\quad 00:52:10 FB 诞生,By:ronargo

题目大意

在这里插入图片描述
\quad 如上图所示,在一个平面直角坐标系的以 ( 0 , 0 ) (0,0) (0,0) 为左下角、 ( N , N ) (N,N) (N,N) 为右上角的矩形中,求在原点向周围看去,能看到多少个点。

分析

\quad 不难(用)证明,一个点 ( x , y ) (x,y) (x,y) 能被看到当且仅当 g c d ( x , y ) = 1 gcd(x,y)=1 gcd(x,y)=1.

\quad 由于 n n n 最大只有 2000 2000 2000,因此我们可以暴力枚举 x x x y y y,时间复杂度为 O ( n 2 l o g ( n ) ) O(n^2log(n)) O(n2log(n)).

\quad 小坑点:特判 n = 1 n=1 n=1 的情形.

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e6;
const int N = (int)5e3;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

void work()
{
    int n; scanf("%d", &n);
    if(n == 1)
    {
        printf("0\n");
        return;
    }
    int ans = 3;
    for(int i = 1; i <= n - 1; ++i) for(int j = 1; j <= n - 1; ++j) ans += (gcd(i, j) == 1);
    printf("%d\n", ans - 1);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1622.蓝精精的浏览器[栈模拟]

出题人:qp \quad 验题人:lhr

\quad 00:57:30 FB 诞生,By:20luwei

题目大意

\quad 题面简单易懂(没看懂的去骂 qp 吧)

分析

\quad 之前 lzw 讲过括号匹配,跟这道题很是相似,直接看代码吧.

\quad 时间复杂度: O ( 能 过 ) O(能过) O().

代码实现

\quad 20luwei 小伙汁代码写得不错,就把你的放出来吧!

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <stack>
using namespace std; 

stack<string> a;
stack<string> b;
string t;
string s;
int forward = 0, back = 0;

int main()
{
	a.push("http://www.acm.org/");
	while(cin >> t)
	{
		if(t == "VISIT")
		{
			while(!b.empty()) b.pop();
			cin >> s;
			a.push(s); 
			cout << a.top() << '\n';
		}
		
		else if(t == "BACK")
		{
			if(a.size() != 1)
			{
				b.push(a.top());
				a.pop();
				cout << a.top() << '\n';
			}
			else
			{
				cout << "Ignored" << '\n';
			}
		}
		
		else if(t == "FORWARD")
		{
			if(!b.empty())
			{
				a.push(b.top());
				b.pop();
				cout << a.top() << '\n';
			}
			else cout << "Ignored" << '\n';
		}
		
		else if(t == "QUIT") break;
	}
	
	return 0;
}

1623.闷声发大财[小思维]

出题人:sly \quad 验题人:lhr、lzw

\quad 01:56:22 FB 诞生,By:2020Wangweiyi

\quad 两个一血了啊,不愧是你!

题目大意

\quad 中文题

分析

\quad 代码里写了注释,自己模拟一下就懂了.

\quad 时间复杂度: O ( m ) O(m) O(m).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e5;
const int N = (int)5e3;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

int n, m;
bool r[M + 5];
bool c[M + 5];
int rcnt, ccnt;

void work()
{
    scanf("%d %d", &n, &m);
    rcnt = n, ccnt = n;
    for(int i = 1, x, y; i <= m; ++i)
    {
        scanf("%d %d", &x, &y);
        if(!r[x]) r[x] = 1, --rcnt;
        if(!c[y]) c[y] = 1, --ccnt;
        printf("%lld%c", 1ll * rcnt * ccnt, i == m ? '\n' : ' ');
    }
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1626.星球大战2[欧拉函数前缀和]

出题人:lra \quad 验题人:lhr、zlk、xwj、lzw、xsh

\quad 再次被 2020Wangweiyi 于03:11:30拿走 First Blood

题目大意

\quad 1625.星球大战1

分析

\quad 1625.星球大战1 的分析

\quad 用力推一下式子,发现答案就是 3 + 2 ∑ i = 1 n − 1 φ ( i ) 3 + 2\sum_{i=1}^{n-1}{\varphi(i)} 3+2i=1n1φ(i),套上线性筛直接搞就行.

\quad 时间复杂度: O ( n ) O(n) O(n).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)4e4;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

bool is_prime[M + 5];
int prime[M + 5], cnt;
int phi[M + 5];//欧拉函数

void init()
{
    memset(is_prime, 1, sizeof(is_prime));
    is_prime[0] = is_prime[1] = 0;
    phi[1] = 1;
    for(int i = 2; i <= M; ++i)
    {
        if(is_prime[i])
        {
            prime[++cnt] = i;
            phi[i] = i - 1;
        }
        for(int j = 1; j <= cnt && i * prime[j] <= M; ++j)
        {
            is_prime[i * prime[j]] = 0;
            if(i % prime[j] == 0)
            {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}

void work()
{
    int n; scanf("%d", &n);
    if(n == 1)
    {
        printf("0\n");
        return;
    }
    ll ans = 3;
    for(int i = 2; i <= n - 1; ++i) ans += 2 * phi[i];
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    init();
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1627.最短的题[枚举]

出题人:xwj \quad 验题人:lhr、lra,lzw

\quad 02:15:08 又又又又 被 2020wangweiyi 拿走 FB

题目大意

\quad 从 n 个数中选 n - 1 个数使得它们或和(或运算的和)最大,输出这个最大值.

分析

\quad 枚举哪一个数不选,暴力更新答案即可.

\quad 时间复杂度: O ( n ) O(n) O(n).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)4e4;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

int n;
ll a[M + 5];
int c[64];

void work()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%lld", &a[i]);
        for(int j = 62; j >= 0; --j) c[j] += (a[i]>>j&1);
    }

    ll mx = 0;
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 62; j >= 0; --j) c[j] -= (a[i]>>j&1);
        ll tmp = 0; for(int j = 62; j >= 0; --j) if(c[j]) tmp |= (1ll<<j);
        mx = max(mx, tmp);
        for(int j = 62; j >= 0; --j) c[j] += (a[i]>>j&1);
    }
    printf("%lld\n", mx);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}
出题人更优秀的做法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-11;
const ll N = 1e5 + 10;

ll a[N], pre[N], las[N];

int main() {
    ll n;
    scanf("%lld", &n);
    for(ll i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    pre[1] = a[1];
    for(ll i = 2; i <= n; ++i) pre[i] = pre[i - 1] | a[i];
    las[n] = a[n];
    for(ll i = n - 1; i >= 1; --i) las[i] = las[i + 1] | a[i];
    ll ans = 0;
    for(ll i = 1; i <= n; ++i)
        ans = max(ans, pre[i - 1] | las[i + 1]);
    printf("%lld\n", ans);
    return 0;
}

1617.HR的双十一[枚举 + 快速幂 + 逆元]

出题人:lzw \quad 验题人:lhr
题目大意

\quad 嗯。

分析

\quad 枚举 i i i 表示第 i i i 天后 LHR 喵币总数 ≥ M \geq M M 且 第 i − 1 i - 1 i1 天后 LHR 喵币总数 < M \lt M <M,那么该情况的收益为 ∑ j = i n 1 = ( n − i + 1 ) ( i + n ) 2 \sum_{j=i}^n{1} = \frac{(n - i + 1)(i + n)}{2} j=in1=2(ni+1)(i+n),发生的概率为 C i − 1 ⌈ M x ⌉ − 1 p ⌈ M x ⌉ ( 1 − p ) i − ⌈ M x ⌉ C_{i - 1}^{\lceil{\frac{M}{x}}\rceil - 1} p^{\lceil{\frac{M}{x}}\rceil}(1-p)^{i - \lceil{\frac{M}{x}}\rceil} Ci1xM1pxM(1p)ixM.

\quad 小坑点:1. 求 p p p 的时候需要求 100 100 100 在模 998244353 998244353 998244353 的逆元
\quad\quad\quad\quad 2. 特判 x = 0 x=0 x=0 k = 0 k = 0 k=0 的情况

\quad 时间复杂度: O ( n l o g ⌈ m x ⌉ ) O(n log\lceil \frac{m}{x} \rceil) O(nlogxm),再用力一点能优化到 O ( n ) O(n) O(n).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e3;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;

int n, x, m, p;
ll c[M + 5][M + 5];

void init()
{
    c[0][0] = 1;
    for(int i = 1; i <= M; ++i)
    {
        c[i][0] = 1;
        for(int j = 1; j <= i; ++j) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
    }
}

ll quick(ll a, ll b, ll p = mod)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return s;
}

ll inv(ll n, ll p = mod)
{
    return quick(n, p - 2, p);
}

void work()
{
    scanf("%d %d %d %d", &n, &x, &m, &p);
    p = p * inv(100) % mod;
    int q = ((1 - p) % mod + mod) % mod;
    ll ans = 0, cur;
    if(x == 0)
    {
        if(m == 0) printf("%lld\n", 1ll * n * (n + 1) / 2 % mod);
        else       printf("0\n");
        return;
    }
    int k = (m + x - 1) / x;
    if(k == 0)
    {
        printf("%lld\n", 1ll * n * (n + 1) / 2 % mod);
        return;
    }
    for(int i = k; i <= n; ++i)
    {
        cur = 1ll * (n - i + 1) * (i + n) / 2 % mod;
        cur = cur * c[i - 1][k - 1] % mod * quick(p, k) % mod * quick(q, i - k) % mod;
        ans = (ans + cur) % mod;
    }
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    init();
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1618.The Guo[思维]

出题人:lzw \quad 验题人:lhr、wx
题目大意

\quad 啊。

分析

\quad 不难想到,如果初始地图所有的锅连在一起,那么最小花费为所有锅的和(一次全部修完,不留给锅精造锅的机会)

\quad 否则你至少需要休息一次。所以不论你如何操作,休息一次之后所有的点上都有锅,那么第二次修锅时就可以把所有锅清除掉。

\quad 时间复杂度: O ( n m ) O(nm) O(nm).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e3;
const int N = (int)5e3;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int n, m;

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

vector<vector<int> > mp;
vector<vector<bool> > vis;

struct node
{
    int x, y;
};

queue<node> q;

void bfs(int x, int y)
{
    node u, v;
    vis[u.x = x][u.y = y] = 1;
    q.push(u);
    while(!q.empty())
    {
        u = q.front(); q.pop();
        for(int i = 0; i < 4; ++i)
        {
            v.x = u.x + dx[i], v.y = u.y + dy[i];
            if(v.x >= 1 && v.x <= n && v.y >= 1 && v.y <= m && !vis[v.x][v.y] && mp[v.x][v.y])
            {
                vis[v.x][v.y] = 1;
                q.push(v);
            }
        }
    }
}

void work()
{
    scanf("%d %d", &n, &m);
    mp.resize(n + 1); vis.resize(n + 1);
    for(int i = 0; i <= n; ++i) mp[i].resize(m + 1), vis[i].resize(m + 1);
    for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) mp[i][j] = read();

    int zero = 0; ll sum = 0; for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) zero += !mp[i][j], sum += mp[i][j];
    int blocks = 0; for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) if(!vis[i][j] && mp[i][j]) bfs(i, j), ++blocks;

    if(blocks == 1) printf("%lld\n", sum);
    else            printf("%lld\n", sum + 1 + zero);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1619.The Super Guo[DFS + 贪心]

出题人:lhr \quad 验题人:syh、ymf、lzw、wx
题目大意

\quad 呀。

分析

\quad 显然,每次选取一个极大连通块是最优的(走到不能走为止),那么问题就变成了如何安排极大连通块的选择顺序,使用临项交换法可知贪心策略就是:优先选择格点数最多的连通块。

\quad 时间复杂度: O ( n m × l o g ( n m ) ) O(nm \times log(nm)) O(nm×log(nm)).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e5;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;

int n, m;

struct node1
{
    int x, y;
};

struct node2
{
    ll sum;
    int cnt;
};

vector<vector<int> > mp;
vector<vector<int> > vis;
vector<node2> block;

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

int read()
{
    int f = 1, x = 0;
    char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

queue<node1> q;

void bfs(int x, int y)
{
    node1 u, v;
    u.x = x, u.y = y;
    q.push(u); vis[u.x][u.y] = 1;
    int cnt = 0; ll sum = 0;
    while(!q.empty())
    {
        u = q.front(); q.pop();
        ++cnt, sum += mp[u.x][u.y];
        for(int i = 0; i < 4; ++i)
        {
            v.x = u.x + dx[i], v.y = u.y + dy[i];
            if(v.x < 1 || v.x > n || v.y < 1 || v.y > m || !mp[v.x][v.y] || vis[v.x][v.y]) continue;
            vis[v.x][v.y] = 1;
            q.push(v);
        }
    }
    node2 tmp;
    tmp.cnt = cnt, tmp.sum = sum;
    block.push_back(tmp);
}

bool cmp(node2 a, node2 b)
{
    return a.cnt > b.cnt;
}

void work()
{
    n = read(); m = read();
    mp.resize(n + 1); vis.resize(n + 1);
    for(int i = 1; i <= n; ++i)
    {
        mp[i].resize(m + 1); vis[i].resize(m + 1);
        for(int j = 1; j <= m; ++j) mp[i][j] = read();
    }
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= m; ++j)
        {
            if(mp[i][j] && !vis[i][j])
            {
                bfs(i, j);
            }
        }
    }
    sort(block.begin(), block.end(), cmp);
    int sz = block.size();
    ll ans = 0;
    for(int i = 0; i < sz; ++i)
    {
        ans += block[i].sum + 1ll * i * block[i].cnt;
    }
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1620.锅精精学数学[组合数学 + 分类讨论]

出题人:ryc \quad 验题人:lhr、lzw
题目大意

\quad 给定整数n,请你求出n的所有合数因子的乘积,由于结果可能过大,请对结果取模998244353。

分析

\quad 由唯一分解定理,将 n n n 表示为 n = p 1 c 1 p 2 c 2 ⋯ p k c k n = p_1^{c_1}p_2^{c_2}\cdots p_k^{c_k} n=p1c1p2c2pkck.

\quad τ ( n ) \tau(n) τ(n) n n n 的正约数的个数,根据乘法原理有 τ ( n ) = ( c 1 + 1 ) ( c 2 + 1 ) ⋯ ( c k + 1 ) \tau(n) = (c_{1} + 1)(c_{2} + 1)\cdots(c_{k} + 1) τ(n)=(c1+1)(c2+1)(ck+1).

\quad π ( n ) \pi(n) π(n) n n n 的正约数的乘积,可以用力求得 π ( n ) = n τ ( n ) 2 \pi(n) = n^{\frac{\tau(n)}{2}} π(n)=n2τ(n).

\quad 然而题目所求为 n n n 的合数因子的乘积,所以答案为 π ( n ) p 1 p 2 ⋯ p k \frac{\pi(n)}{p_1p_2 \cdots p_k} p1p2pkπ(n).

\quad 小细节: π ( n ) = n τ ( n ) 2 \pi(n) = n^{\frac{\tau(n)}{2}} π(n)=n2τ(n) τ ( n ) \tau(n) τ(n) 可能为奇数,此时不能直接除以 2 2 2。由于 τ ( n ) \tau(n) τ(n) 为奇数,即 ( c 1 + 1 ) ( c 2 + 1 ) ⋯ ( c k + 1 ) (c_{1} + 1)(c_{2} + 1)\cdots(c_{k} + 1) (c1+1)(c2+1)(ck+1) 为奇数,可知 c 1 , c 2 , ⋯   , c k c_1,c_2,\cdots,c_k c1,c2,,ck 都是偶数,即 n n n 为完全平方数,此时 n 1 2 n^{\frac{1}{2}} n21 为整数,所以 π ( n ) \pi(n) π(n) 可表示为 ( n 1 2 ) τ ( n ) (n^{\frac{1}{2}})^{\tau(n)} (n21)τ(n).

\quad 小坑点:特判 n % 998244353 = 0 n \% 998244353 = 0 n%998244353=0 的情况.

\quad 时间复杂度: O ( n + l o g ( n ) l o g ( 998244353 ) ) O(\sqrt{n} +log(n) log(998244353)) O(n +log(n)log(998244353)).

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e7;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;

bool is_prime[M + 5];
int cnt, prime[M / 10 + 5];

int m;
struct node
{
    ll p; int c;
    node(ll _p = 0, int _c = 0): p(_p), c(_c){}
}v[100];

void init()
{
    memset(is_prime, 1, sizeof(is_prime));
    cnt = is_prime[0] = is_prime[1] = 0;
    for(int i = 2; i <= M; ++i)
    {
        if(is_prime[i]) prime[++cnt] = i;
        for(int j = 1; j <= cnt && i * prime[j] <= M; ++j)
        {
            is_prime[i * prime[j]] = 0;
            if(i % prime[j] == 0) break;
        }
    }
}

void divide(ll n)
{
    m = 0;
    for(int i = 1; i <= cnt && 1ll * prime[i] * prime[i] <= n; ++i)
    {
        if(n % prime[i] == 0)
        {
            ll c = 0;
            while(n % prime[i] == 0) ++c, n /= prime[i];
            v[m++] = node(prime[i], c);
        }
    }
    if(n > 1) v[m++] = node(n, 1);
}

ll quick(ll a, ll b, ll p = mod)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s;
}

ll inv(ll n, ll p = mod)
{
    return quick(n, p - 2, p);
}

void work(ll n)
{
    if(n == 998244353)
    {
        printf("1\n");
        return;
    }
    if(n % 998244353 == 0)
    {
        printf("0\n");
        return;
    }
    divide(n);
    ll k = 1;
    for(int i = 0; i < m; ++i) k *= v[i].c + 1;
    ll sq = (ll)(sqrt(n) + eps);
    if(sq * sq == n) n = sq;
    else             k /= 2;
    ll ans = quick(n % mod, k);
    for(int i = 0; i < m; ++i) ans = ans * inv(v[i].p % mod) % mod;
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    init();
    ll n; while(~scanf("%lld", &n)) work(n);
//    work();
//    int T; scanf("%d", &T);
//    while(T--) work();
    return 0;
}

1621.加密通话[思维]

出题人:zlk \quad 验题人:lzw
题目大意

\quad 呱。

分析

\quad 按照二进制位分析 So Easy.

\quad 只需要在题目所给代码的基础上加 3 3 3 行即可 AC.

\quad 时间复杂度: O ( n 2 n ) O(n2^n) O(n2n)

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e3;
const int N = (int)5e3;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;

char s[M + 5];

void work()
{
    scanf("%s", s + 1);
    int n = (int)(log2(strlen(s + 1)) + eps) + 1;
    int p = 0;
    for(int i = 0; i < n; ++i)
    {
        int t = 0;
        for(int j = 1; j <= (1<<n) - 1; ++j)
        {
            if((1<<i)&j)    t ^= s[j];
        }
        if(t) p |= (1<<i);
    }
    s[p] ^= 1;
    printf("%s\n", s + 1);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    work();
    int T; scanf("%d", &T);
    while(T--) work();
    return 0;
}

1624.新型冠状病毒[组合数学]

出题人:lhr \quad 验题人:lzw
题目大意

\quad 哞。

分析

\quad 显然 答案为 C t x C t − x y C_t^xC_{t-x}^y CtxCtxy.

\quad 时间复杂度: O ( 1 0 7 + T l o g ( 998244353 ) ) O(10^7 + Tlog(998244353)) O(107+Tlog(998244353))

代码实现
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int M = (int)1e7;
const int N = (int)1e5;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;

ll fac[M + 5];

ll quick(ll a, ll b, ll p = mod)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s;
}

ll inv(ll n, ll p = mod)
{
    return quick(n, p - 2, p);
}

ll c(int n, int m)
{
    return fac[n] * inv(fac[m]) % mod * inv(fac[n - m]) % mod;
}

void work()
{
    int x, y, t;
    scanf("%d %d %d", &x, &y, &t);
    if(x > t || y > t - x) {printf("0\n"); return;}
    ll ans = 1;
    ans = ans * c(t, x) % mod;
    ans = ans * c(t - x, y) % mod;
    printf("%lld\n", ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    work();
    fac[0] = 1; for(int i = 1; i <= M; ++i) fac[i] = fac[i - 1] * i % mod;
    int T; scanf("%d", &T);
    while(T--) work();
    return 0;
}

吐槽

  1. 办比赛真累,以后不想搞了(真香)。
  2. 这群人怎么回事,学了一个多月,除了暴力啥也不会(其实暴力也不会)?下周不得被齐工大锤爆

END

所以说,知道自己的真实实力最重要,不要因为一时的失败就觉得自己不行。

一定要多试几次你才会知道,自己真的不行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值