Codeforces Round #489 (Div. 2)

A.
稍加思考就会发现其实只要知道其中非0的不同的数有多少个就可以了。

#include<cstdio>
#include<iostream>
#include<set>
using namespace std;
int main()
{
    int n,i,j;
    set<int>s;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>j;
        if(j)s.insert(j);
    }
    cout<<s.size()<<endl;

    return 0;
}

B.
记a=GCD*n, b=GCD * m,那么必有LCM=GCD * n * m, 所以可以计算出LCM/GCD,然后枚举这个数的所有分解判断他们是否互质即可。需要注意的是坑爹数据包含了LCM不能整除GCD的情况…

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int gcd(int x,int y)
{
    return y?gcd(y,x%y):x;
}
int main()
{
    int l,r,x,y,i,j,k;
    bool issame=false;
    cin>>l>>r>>x>>y;
    if(y%x){
        cout<<0<<endl;return 0;
    }
    k=y/x;
    ll cnt=0;
    for(i=1;i*i<=k;i++){
        if(k%i==0){
            j=k/i;
            if(i*x<l||i*x>r||j*x<l||j*x>r)continue;
            if(gcd(i,j)!=1)continue;
            cnt++;
            if(i==j)issame=true;
        }
    }
    cnt*=2;
    if(issame)cnt--;
    cout<<cnt<<endl;

    return 0;
}

C.
题目求的期望值看起来挺麻烦的,但其实50%的几率发生,那么期望值其实就是每次*2-0.5 …,然后最后一次只要 *2即可,我们会发现可以把这个2乘进去,然后这个式子就可以化简为 x *2^(k+1)-(2^k-1),做两次快速幂即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll mod_pow(ll x, ll n, ll mod)
{
    ll res = 1;
    while (n) {
        if (n & 1)
            res = res*x%mod;
        x = x*x%mod;
        n >>= 1;
    }
    return res;
}
int main()
{
    ll x,k,i,j;
    cin>>x>>k;
    if(!x){
        cout<<0<<endl;return 0;
    }
    x%=mod;
    ll res=mod_pow(2,k+1,mod);res=res*x%mod;
    ll minus=mod_pow(2,k,mod);minus-=1;
    ll ans=(res-minus+mod)%mod;
    cout<<ans<<endl;

    return 0;
}

D.
题目的做法比较不好描述,大致思想是预处理整个数列,跳过所有那些值为1的数,然后记录每个数的下一个值不为1 的数的位置(数组下标),然后用一个O(n^2)的暴力算法去找这样的序列,因为去除1以后已经优化了很多,所以似乎并不会tle

#include<cstdio>
#include<iostream>
using namespace std;
long long p,s;
int main()
{
    int ans=0,n,a[200005],next1[200005],pre,i,j,k;
    cin>>n>>k;
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    pre=n+1;
    for(i=n;i>0;i--) {
        next1[i] = pre;
        if (a[i] > 1)pre = i;
    }
    for(i=1;i<=n;i++) {
        p = 1;s = 0;
        for (j = i; j <= n; j = next1[j]) {
            if (a[j] > 2e18/p )break;
            p *= a[j];
            s += 1LL * k * a[j];
            if (p == s)ans++;
            if (p > s && (p - s) % k == 0 && (p - s) / k <= next1[j] - j - 1)ans++;
            s += 1LL * k * (next1[j] - j - 1);
        }
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值