2021牛客多校7(H,I),多校8(A,D,E,K).

多校7:
H. xay loves count
题目:给了数组a, 求三元组(i, j, k)的数量,使得 a i _i i * a j _j j = a k _k k
思路:对于a * b = c来说,如果我们知道了c, 那么就可以从 1到 c \sqrt{c} c 找a, 然后通过a去判断b。
这里可以用一个map把数量存下来,然后遍历 c \sqrt{c} c 就好。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
int b[N];
int n;
map<int, int> mp;

int main(){
    cin >> n;
    for(int i = 1; i <= n; i++) 
    {
        cin >> b[i];
        mp[b[i]]++;
    }
    ll ans = 0;
    for(auto x : mp)
    {
        int u = x.first, y = x.second;
        for(int i = 1; i <= sqrt(u); i++)
        {
            if(u%i == 0 && mp[u/i] && mp[i]){
               if(i == u/i){ //相等的时候i, j不能交换位置
                   ans += y*mp[i]*mp[u/i];
               }else{
                   ans += 2*y*mp[i]*mp[u/i];
               }
            }
        }
    }
    cout << ans << endl;
}

I. xay loves or
题目:给你x和s,你需要计算有多少正整数y满足 x or ⁡ \operatorname{or} or y=s。
思路:我们看二进制中的规律,对于s中的1,如果在x上没有,那么在y上一定有,如果在x上有,那么在y上不一定有。因此y的变化只有x上的1. 所有统计x的1就好。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

void solve(){
    ll x, s;
    cin >> x >> s;
    if((( x | s) > s) || (x > s)) {
        cout << 0 << endl;
        return ;
    }
    ll cot1 = 0, cot2 = 0;
    ll n = x;
    while(n){
        if(n & 1) cot1++;
        n >>= 1;
    }
    ll ans = 1;
    for(int i = 1; i <= cot1; i++) ans *= 2;
    if(x == s) {
        cout << ans-1 << endl;
    }else{
        cout << ans << endl;
    }
}

int main(){
    solve();
}

多校8:
A. Ares, Toilet Ares
题目:太长了… 总之就是求一个能过题目的期望(照着题目下面写)。
思路:一开始没看懂,然后怀着忐忑的心情用了除法取模,然后答案就出来了…。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
const int mod = 4933;
const int N = 1e5 + 10;

int ksm(int a, int n)
{
    int ans = 1;
    a %= mod;
    while(n){
        if(n & 1) ans = ans*a % mod;
        a = a*a % mod;
        n >>= 1;
    }
    return ans;
}

signed main(){
    int n, m, k, a, l;
    cin >> n >> m >> k >> a >> l;
    ll ans = 1;
    if(k == 0) ans = 0;
    for(int i = 1 ; i <= k; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        if(x == 0) continue;
        ans = ans*(z-y)%mod*ksm(z, mod-2)%mod;
    }
    cout << ((ans+a)%mod) << endl;
}

D. OR
题目:就是说给你长度n - 1的b数组和c数组。一个代表a i − 1 _{i-1} i1 or ⁡ \operatorname{or} or a i _{i} i, 一个代表a i − 1 _{i-1} i1 + ⁡ \operatorname{+} + a i _i i。然后问有多少个数组a满足要求。
思路:我们首先看一个知识点:a + b = a ∣ ⁡ \operatorname{|} b + a & \& &b。 所以我们可以得到的两个数组。然后很容易观察到只要确定了a 1 _1 1,那么后面的数就确定了。暴力的方法是枚举,但是a最多有230个,所以会T。这里用更简单的思路,我们对每一位二进制分别做一次就好。
就是说我们这里不看整体,只看二进制第一位符不符合,第二位符不符合。

我们分别列举为0和为1的情况,然后简单的逻辑推导。如果b是1且d是1,那么两个一定是1,如果都是0,那么两个都是0。如果一个1一个0,只有b = 1, d = 0时可以,且上一个是1则下一个是0,上一个是0则下一个是1。 – 按照这样的思路写一遍。

代码上比较简洁,而且很是离谱,总之我是想不出来,都是根据大佬们的思路做了一遍后才会做。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define _ 0
const int maxn = 1e5 + 10;
int b[maxn], c[maxn], d[maxn];
int n;
ll ans = 0;


int main(){
    cin >> n;
    for(int i = 2; i <= n; i++) cin >> b[i];
    for(int i = 2; i <= n; i++) cin >> c[i];
    for(int i = 2; i <= n; i++){
        d[i] = c[i] - b[i];
    }
    ll ans = 1;
    for(int i = 0; i <= 31; i++)
    {
        int bt0 = 1, bt1 = 1; //存储0和1的可能性
        for(int j = 2; j <= n; j++){
            int x = (b[j]>>i)&1, y = (d[j]>>i)&1;
            int btt0 = 0, btt1 = 0;
            if(x == 0 && y == 0) btt0 = bt0;
            if(x == 1 && y == 1) btt1 = bt1;
            if(x == 1 && y == 0) btt1 = bt0, btt0 = bt1;
            bt1 = btt1, bt0 = btt0;
        }
        ans *= (bt0 + bt1);
    }
    cout << ans << endl;
	return ~~(0 ^_^ 0);
}  

E. Rise of Shadows
题目:找一个质数闰年。
思路:好家伙,竟然有闰年的质数…

#include<iostream>
int main(){
    int t;
    std::cin >> t;
    while(t--){
        int n;
        std::cin >> n;
        std::cout << "no\n";
    }
}

K. Yet Another Problem About Pi
题目:给出网格宽和高,然后求能走 π \pi π 的长度下能走的最多的网格。
思路:由于没有限定条件,我们就可以把边界线看成无限细但真实存在。而我们的线在线上走可以同时经过边界的两个面 (话说也没有规定我的线有多粗,万一我的车比行星大呢 🙄)。所以我们就要尽量走顶点。我们看一下,如果走最短边,那么下一次就会增加2的能到的块,如果走对角线,那么下一次就增加3的块。所以我们就要看走那边最好。然后暴力枚举。至于为什么是枚举到2,是因为你走的线路只有在一开始和最后会有所改变。(应该算是贪心)
代码:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const double pai = acos(-1.0);
int main()
{
    int t;
    cin >> t;
    while (t--) {
        double w, d;
        cin >> w >> d;
        double a = min(w, d), b = sqrt(w * w + d * d);
        ll ans = 0;
        for (int i = 0; i <= 2; i++) {
            if (pai - a * i >= 0) ans = max(ans, (ll)(4 + i*2 + (int)((pai-a*i)/b) * 3));
            if (pai - b * i >= 0) ans = max(ans, (ll)(4 + i*3 + (int)((pai-b*i)/a) * 2));
        }
        cout << ans << endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值