牛客_____Wannafly挑战赛29______魔禁场

目录

御坂美琴

白井黑子

左方之地


御坂美琴

あなたの指先が躍動する電気の光は、私の不滅の信仰である!

题解:对每一个数进行题述操作就ok,直到不能拆为止,对操作得到的数字,用map 标记一下(1表示可以得到,0表示得不到),最后再跑一遍,核对一遍。


misaka是呱太爷爷的小粉丝,呱太爷爷有一句话说的好:"一尺之棰,日取其半,万世不竭"。

misaka现在有 n 个呱太玩偶放在一堆,每一次操作,misaka会选择当前个数 > 1 的一堆呱太玩偶。并将这一堆呱太玩偶分成 x/2和x-x/2  两堆,x 是当前这一堆玩偶的个数。现在 misaka 想将玩偶分成 m 堆,其中第 i 堆呱太玩偶的个数是 ai ,你需要告诉 misaka 是否能通过若干次操作将玩偶分成指定的这 m 堆。如果可以输出  misaka,否则输出ham  。

输入描述:

第一行两个数 n, m 。
接下来一行 m 个数 ai 。
输出描述:

输出共一个字符串 ,表示 misaka 能否将玩偶分成指定的 m 堆。

示例1

输入

4 1
5
输出

ham
备注:

1 ≤ n ≤ 1e18, 1 ≤ m ≤ 1e5, 1 ≤ ai ≤ 1e18。

 

Ac代码,思路转载自

#include
using namespace std;
typedef long long ll;
const int maxn = 2e5+7;
ll n,m,a[maxn],sum;
map M;
void dfs(ll t){
    if(M[t])return;
    M[t] = 1;
    if(t == 1)
        return;
    dfs(t/2),dfs(t-t/2);
}
int main(){
    cin>>n>>m;
    for(int i=0;i>a[i],sum += a[i];
    if(sum != n)
        return 0*printf("ham\n");
    dfs(n);
    for(int i=0;i

 

白井黑子

 

题目描述

kuroko 作为常盘台唯一的空间系能力者,在每年例行的能力测试中可绝对不能让 misaka 失望哦,但是由于她的等级只是 level 4「大能力者」,在能力测试中会遇到不少困难。kuroko 是一个凡事都会尽力的好女孩,所以请你帮她算出她最多能完成多少测试吧

对于空间系能力者测试的内容是检验对物体进行空间移动的能力,测验时一共有 n 个物品放在一条直线上,每个物品都有一个坐标 ai ,kuroko 可以选择两个物品并使用能力交换它们的位置,但是如果两个物品的坐标不满足 kuroko 的计算公式的话,她就没有办法使用能力。

具体来说,对于坐标 ai ,其在 kuroko 的计算公式中是用参数 f(ai) 表示的。f(ai) 是 ai 各数位相乘的结果,由于 level 4「大能力者」在学园都市中也是很强大的存在,所以满足公式的条件不会太苛刻,对于两个物品 ai, aj ,如果 f(ai) x f(aj) 不能被某个自然数的 k 次幂表示 的话,那么 kuroko 就能对这两个物品使用能力

现在 kuroko 想知道,有多少对物品她可以对其施展能力,知道了这个后她就知道自己能完成多少测验了。

这里认为任何自然数的 0 次幂都是 1。

输入描述:

第一行两个数,n, k 。

第二行共 n 个数 ai 表示这 n 个物品在直线上的坐标。
输出描述:

输出共一个数,表示 kuroko 能对其使用能力的无序物品对数。

示例1

输入

复制

6 3
113 10 11 1110 33 110

输出

复制

2

转载自

 

 

牛客_____Wannafly挑战赛29______魔禁场_第1张图片

 

 

Ac代码(我改出来的一种方式-->让我的话是想不到每一步对ans加的,所以在最后扫一遍)

#include 
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
bool vis[maxn];
ll n,k,a[maxn],ans=0;
struct node{
    ll s[4];
    void init(){
        for(int i=0;i<4;i++)
            s[i]=(k-s[i]%k)%k;
    }
    bool operator < (const node &a) const{
        for(int i=0;i<4;i++)
            if(s[i]!=a.s[i])
                return s[i] mmp;
ll fen(ll x){
    if(x==0) return 0;
    ll ans = 1;
    while(x){
        ans *= x%10;
        x/=10;
    }
    return ans;
}
int fff[4]={2,3,5,7};
bool operator == (node a,node b){
    for(int i=0;i<4;i++)
        if(a.s[i]!=b.s[i])
            return 0;
    return 1;
}
int main(){
    cin>>n>>k;
    for(ll i=1;i<=n;i++)
        cin>>a[i],a[i]=fen(a[i]);
    if(k==1)///k=1,0就满足一切
        return 0*printf("0\n");
    if(k==0){///k=0时,kuroko能移动的是不能被x^k(x^0(其实就是1))表示的,也就是说,不是1的都能移动
        ll cnt_one = 0;///1的个数
        for(ll i=1;i<=n;i++)
            if(a[i]==1) cnt_one++;
        ll complement = n - cnt_one;///不是1的
        ans=complement*cnt_one+(complement-1)*complement/2;
        ///两个数相乘,不是1的两两组合 + 1和不是1的组合
    }
    else{
        ll cnt=0;
        for(ll i=1;i<=n;i++){
            if(a[i]==0){ vis[i] = 1;continue;}///0不合法,没有哪个数的k次幂是0(0^0=1)
            for(int j=0;j<4;j++){
                while(a[i]%fff[j]==0){
                    A[i].s[j]++;///统计当前的每个值的个数
                    a[i]/=fff[j];
                }
            }
            A[i].init();///取反
            //ans += mmp[A[i]];///ans记录的是
            A[i].init();///再正过来
            mmp[A[i]]++;///当前++
            cnt++;///统计有多少个合法的
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                node P = A[i];
                A[i].init();
                if(P == A[i])
                    ans--;
                ans += mmp[A[i]];
            }
        }
        ans=(cnt-1)*cnt/2-ans/2;///拿总的减掉能被x^k表示(不能移动的)
    }
    cout<

 

另一种,ans在处理过程中加上去

#include 
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
ll n,k,a[maxn],ans=0;
struct node{
    ll s[4];
    void init(){
        for(int i=0;i<4;i++)
            s[i]=(k-s[i]%k)%k;
    }
    bool operator < (const node &a) const{
        for(int i=0;i<4;i++)
            if(s[i]!=a.s[i])
                return s[i] mmp;
ll fen(ll x){
    if(x==0) return 0;
    ll ans = 1;
    while(x){
        ans *= x%10;
        x/=10;
    }
    return ans;
}
int fff[4]={2,3,5,7};
int main(){
    cin>>n>>k;
    for(ll i=1;i<=n;i++)
        cin>>a[i],a[i]=fen(a[i]);
    if(k==1)///k=1,0就满足一切
        return 0*printf("0\n");
    if(k==0){///k=0时,kuroko能移动的是不能被x^k(x^0(其实就是1))表示的,也就是说,不是1的都能移动
        ll cnt_one = 0;///1的个数
        for(ll i=1;i<=n;i++)
            if(a[i]==1) cnt_one++;
        ll complement = n - cnt_one;///不是1的
        ans=complement*cnt_one+(complement-1)*complement/2;
        ///两个数相乘,不是1的两两组合 + 1和不是1的组合
    }
    else{
        ll cnt=0;
        for(ll i=1;i<=n;i++){
            if(a[i]==0) continue;///0不合法,乘出来还是0
            for(int j=0;j<4;j++){
                while(a[i]%fff[j]==0){
                    A[i].s[j]++;///统计当前的每个值的个数
                    a[i]/=fff[j];
                }
            }
            A[i].init();///取反
            ans += mmp[A[i]];///ans记录的是
            A[i].init();///再正过来
            mmp[A[i]]++;///当前++
            cnt++;///统计有多少个合法的
        }
        ans=(cnt-1)*cnt/2-ans;///拿总的减掉能被x^k表示(不能移动的)
    }
    cout<

C

左方之地

左方之地是全宇宙最帅的男人,由于有人嫉妒他的帅气,他决定出一道题考一考这些嫉妒他帅气的人。

左方之地现在手上有 n 件不同的灵装,第 i 件灵装有一个帅气值 ai ,现在他将灵装随机摆成一个排列,并将这个排列映射到一棵二叉树上,这棵二叉树的中序遍历是原排列,且每一个节点上的灵装编号都要小于其子树中的所有点的灵装编号。可以证明对于一个排列,这样的二叉树的形态是唯一的。

这棵树会产生一个总的帅气值等价于树上每个节点的灵装的帅气值乘上该节点的深度(根节点的深度为 1)之和,左方之地想让你求出期望能获得的总帅气值在膜 998244353 意义下的结果是多少

链接:https://ac.nowcoder.com/acm/contest/271/C
来源:牛客网
 

输入描述:

第一行一个数 n。
接下来 n 行,第 i 行一个整数 ai 。

输出描述:

输出共一个数,表示答案。

 

示例1

输入

3
1
1
1

输出

665496241

备注:

1 ≤ n ≤ 1e5, 1≤ ai ≤ 1e9

一个大佬的题解

 

大佬的结果还能继续化简

 

emmm

最后结果是

s[n]=\sum_{i=1}^{n}A[i]

ans = s[n]+\sum_{i=1}^{n}(2*\frac{s[n]-s[i]}{i+1})

 

线性求逆元的一种方法

设t=P/i,k=P%t
则有 t*i+k≡0(%P)
有 −t*i≡k(%P)
两边同时除以i*k得到 
−t*inv[k]≡inv[i](%P)
即inv[i]≡−P/i*inv[P%i](%P)
即inv[i]≡(P−P/i*inv[P%i](%P)

并不是那个对应的代码

#include
using namespace std;
typedef long long ll;
const int mod=998244353,maxn=1e5+10;
ll s[maxn],inv[maxn];
int n;
void Getinv(){
    inv[1]=1;
    for(int i=2;i<=n+2;i++)
        inv[i]=inv[mod%i]*(mod-mod/i)%mod;
}
void input(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&s[i]),s[i]=(s[i-1]+s[i])%mod;
}
int main(){
    input();
    Getinv();
    ll ans=s[n];
    for(int i=1;i<=n;i++)
        ans += inv[i+1]*2*(s[n]-s[i]+mod)%mod;
    printf("%lld\n",ans%mod);
    return 0;
}

 

你可能感兴趣的:(牛客_____Wannafly挑战赛29______魔禁场)