2020牛客暑期多校训练营(第七场)[ B , D , H ]题解

B - Mask Allocation

Nowadays, the Kingdom of Dreamgrid is suffering from a national pandemic. Fortunately, president Baobao is working effectively with the Center for Disease Control (CDC) and they are trying their best to make everything under control.

President Baobao has received n x m medical masks from his friend Reku, an extremely rich billionaire. As the chief of the CDC, you are required to allocate these masks properly. There are 2 kinds of hospitals in the Kingdom of Dreamgrid, n senior hospitals for critically ill patients and m mobile cabin hospitals for patients with mild symptoms.

Before allocating them to hospitals, you have to pack them into boxes. Please note that boxes must not be opened in order to prevent contamination and you only know these boxes will be allocated to either senior hospitals or mobile cabin hospitals. That is to say, there should be a way of dividing masks boxes into m groups of n masks, and a way of dividing into n groups of m masks.

You want the number of boxes to be minimal and please also provide a lexicographically greatest sequence of the numbers of masks in boxes. We say a sequence a is lexicographically greater than another b of the same length if there exists an integer i, such that a j = b j a_j = b_j aj=bj for all j < i; and a i < b i a_i < b_i ai<bi.

输入

There are multiple test cases. The first line of the input contains an integer T ( 1 ≤ T ≤ 100 ) T(1≤T≤100) T(1T100), indica1ting the number of test cases.

For each test case, the only line of the input contains two integers n , m ( 1 ≤ n , m ≤ 1 0 4 ) n,m(1≤n,m≤10^4) n,m(1n,m104), representing the numbers of senior hospitals and mobile cabin hospitals.

输出

For each test case, please output two lines. The first line should contain a single integer k in the first line, indicating the minimum number of boxes. In the second line, please output k integers, denoting the lexicographically greatest sequence.

样例

input
2
5 4
3 3
output
8
4 4 4 4 1 1 1 1
3
3 3 3

思路

对于样例n=5,m=4。可以先包装出4个4,满足5个4中的4个,但是不超出4个5个数条件,接下来需要包装出1个4,同时可以和4个4组合包装出4个5,就相当于求n=1,m=4的情况,由此可以得出规律:
设题目所求的答案遵循ans=A(n,m),因此对于题目所给数据不断递归,寻找A(n-m,m),当m=1时,包装出n个1结束;或n=m时包装出n个m结束。

my Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2020-08-01 13:52:14
 * @LastEditTime: 2020-08-01 14:52:42
 */
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>

#define ll long long
#define db double
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define rep(l, a, b) for (ll l = a; l < b; ++l)
#define per(l, a, b) for (ll l = a; l >= b; --l)
#define debug(a) cout << '#' << a << '#' << endl

using namespace std;
bool fi = true;
const unsigned long long MOD = 1e9 + 7;

ll gcd(ll a, ll b) { return (b == 0 ? a : gcd(b, a % b)); }

vector<int> ans;

void dfs(int n, int m) {
    // debug(n);
    // debug(m);
    if (m == 1) {
        rep(i, 0, n) ans.push_back(1);
        return;
    }
    if (m == n) {
        rep(i, 0, n) ans.push_back(n);
        return;
    }
    rep(i, 0, m) ans.push_back(m);
    if (n - m > m)
        dfs(n - m, m);
    else
        dfs(m, n - m);
    return;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t;
    scanf("%d", &t);
    while (t--) {
        int n, m;
        scanf("%d%d", &n, &m);
        if (n < m) swap(n, m);
        if (n == m) {
            printf("%d\n", n);
            rep(i, 0, n) printf("%d%c", n, (i == n - 1 ? '\n' : ' '));
        } else {
            dfs(n, m);
            printf("%d\n", ans.size());
            sort(ans.begin(), ans.end());
            for (int i = ans.size() - 1; i >= 0; i--)
                printf("%d%c", ans[i], (i == 0 ? '\n' : ' '));
        }
        ans.clear();
    }
}

D - Fake News

McDonald Thumb, the greatest president ever in the history of the Great Tokitsukaze Kingdom has held his 100th press conference about the global pandemic after making his 1000000th tweets with his smartphone. With a big smile on his face, Mr. Thumb said that nobody knows math more than he does.

‘I learn math since I was born and I am very good at it’, said Mr. Thumb. ‘People keep asking me why I know math so much and I sometimes find myself having those amazing ideas about math.’

‘For example?’, asked by a reporter.

‘Oh you, I know you! Fake news! You and your agency always produce fake news!’, replied angrily by Mr. Thumb. ‘Let me teach you something, do you know if you add up the squares of numbers from 1 to n, the sum will never be a square number?’
As another reporter in that press conference, you also wondering that given n, whether ∑ k = 1 N k 2 \sum_{k=1}^N k^2 k=1Nk2 is a square number. Specifically, we regard a positive number x as a square number when there exists an integer y satisfying y 2 = x y^2 = x y2=x.

输入

There are multiple test cases. The first line of the input contains an integer T ( 1 ≤ T ≤ 1 0 6 ) T(1≤T≤10^6) T(1T106) indicating the number of test cases.
For each test case, the first line contains one integers n ( 1 ≤ n ≤ 1 0 15 ) n(1≤n≤10^{15}) n(1n1015).

输出

If the sum is a square number, please output Fake news! in one line. Otherwise, please output Nobody knows it better than me! instead.

样例

input
5
1
2
3
4
5
output
Fake news!
Nobody knows it better than me!
Nobody knows it better than me!
Nobody knows it better than me!
Nobody knows it better than me!

思路

对于前n项自然数的平方和是否为平方数,可以用平方和公式先计算出结果a,再用判断a是否为自然数的平方。
在这里插入图片描述

my Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2020-08-01 12:05:52
 * @LastEditTime: 2020-08-01 12:12:00
 */
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>

#define ll long long
#define db double
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define rep(l, a, b) for (ll l = a; l < b; ++l)
#define per(l, a, b) for (ll l = a; l >= b; --l)
#define debug(a) cout << '#' << a << '#' << endl

using namespace std;
bool fi = true;
const unsigned long long MOD = 1e9 + 7;

ll gcd(ll a, ll b) { return (b == 0 ? a : gcd(b, a % b)); }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t;
    scanf("%d", &t);
    unsigned long long n;
    while (t--) {
        scanf("%llu", &n);
        unsigned long long a = ((n + 1) * (2 * n + 1) * n) / 6;
        unsigned long long sqrta = floor(sqrt(a));
        if (sqrta * sqrta == a)
            printf("Fake news!\n");
        else
            printf("Nobody knows it better than me!\n");
    }
}
  • ps.看了dalao们的代码发现实际上只有n=1和n=24时a为平方数
    对于为何只有1和24请戳→[知乎传送门]

  • pps.经过指正 发现当n数量级大于 1 0 6 10^6 106时a会溢出,本人正因为满足“Fake news”的情况数据都很小而恰好AC,感谢指正!这题真正的正确做法如下
    直接贴上官方PPT:
    在这里插入图片描述

H - Dividing

The following rules define a kind of integer tuple - the Legend Tuple:

  • (1, k) is always a Legend Tuple, where k is an integer.
  • if (n, k) is a Legend Tuple, (n + k, k) is also a Legend Tuple.
  • if (n, k) is a Legend Tuple, (nk, k) is also a Legend Tuple.

We want to know the number of the Legend Tuples (n, k) where 1 ≤ n ≤ N , 1 ≤ k ≤ K 1≤n≤N,1≤k≤K 1nN,1kK.

In order to avoid calculations of huge integers, report the answer modulo 1 0 9 + 7 10^9+7 109+7 instead.

输入

The input contains two integers N N N and K K K, 1 ≤ N , K ≤ 1 0 12 1≤N,K≤10^{12} 1N,K1012.

输出

Output the answer modulo 1 0 9 + 7 10^9+7 109+7.

样例

input
3 3
output
8
input
3 9
output
14

思路

如样例N=3,K=9,当k=1,2…8,9时,合法元组的个数分别是3,3,2,1,1,1,1,1,1.
可以看出在一定范围内,不同k的元组个数是相同的,所以对于所有k进行分组,计算组内元组个数总和,相加即可。

Accepted code

虽然学到队内dalao的思想,但是代码没A出来,先贴下学长的代码:

#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
 
int n,k;
 
ll cal(ll n,ll k){
    ll ans=0;
    for(ll l=2,r;l<=k;l=r+1){
        r=n/(n/l);
        if(r>k) r=k;
        //cout<<l<<" "<<r<<endl;
        ll res=(r-l+1)%Mod;
        ans=(ans+(n/l)*res%Mod*2%Mod)%Mod;
        if(n%r==0) res--;
        ans=(ans+res)%Mod;
        //cout<<ans<<endl;
    }
    return ans;
}
 
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll n,k;
    cin>>n>>k;
    ll ans=n%Mod;
    if(k==1){
        cout<<ans<<endl;
        return 0;
    }
 
    if(k>=n) ans=(ans+cal(n,n))%Mod;
    else ans=(ans+cal(n,k))%Mod;
 
    if(k>n) ans=(ans+k-n)%Mod;
    cout<<ans<<endl;
 
    return 0;
}

T h a n k s Thanks Thanks f o r for for w a t c h i n g watching watching

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值