Codeforces Round #520 (Div. 2)B、C

B. Math

這題有點難,但A的人多,莫名其妙的。。

將n唯一分解一下,看最高的一個素數次方是否是2的x次方,若不是,則花費一次操作乘上某個數,將所有的素數的次方變成某個2的x次方,這樣就可以一直開根號拉。

//開啓補題模式?
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e6+10;
int a[N],b[N];
bool p[N];
vector<int>prime;
int main()
{
    int n;cin>>n;
    int len=0,i=2;
    while(n>1)
    {
        if(i>n) break;
        if(n%i==0)
        {
            int t=i;
            a[++len]=i;
            while(n%t==0){n/=t;b[len]++;}
        }
        ++i;
    }
    int mx=0;
    for(int i=1;i<=len;++i) mx=max(mx,b[i]);

   int cur=mx;
   int flag=0;
   for(int i=0;i<=21;++i)
   {
       int w=pow(2,i);
       if(mx==w){cur=i;break;}
       if(mx<w) {cur=i,mx=w;break;}
   }
    int ans=1;
    rep(i,1,len)
    {
        if(b[i]!=mx) flag=1;
        ans*=a[i];
    }
    printf("%d %d\n",ans,cur+flag);
}

C. Banh-mi 

容斥做法

C題自己在草稿紙畫可以得出下面的情況,假設一個串爲111000,且選的區間是[1,6]

答案就是1*6+2*5+4*4+7*3+14*2+28*1.

看起來毫無規律,再來看111111的情況:答案是1+2+4+8+16+32==pow(2,6)-1;

而之前的000,不就是從8+16+32變成了 7+14+28===>少了1+2+4,這一部分就是pow(2,3)-1

代碼:

//開啓補題模式?
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const ll mod=1e9+7;
const int N=1e5+10;
char s[N];
ll sum[N],a[N];
int main()
{
    int n,q;
    cin>>n>>q;
    cin>>s+1;
    a[0]=1;
    for(int i=1;i<=n;++i) a[i]=a[i-1]*2%mod;
    rep(i,1,n)
    {
        sum[i]=sum[i-1]+s[i]-'0';
    }
    int l,r;
    while(q--)
    {
        cin>>l>>r;
        int one=sum[r]-sum[l-1];
        int zero=r-l+1-one;
        ll ans=((a[r-l+1]-a[zero])%mod+mod)%mod;
        printf("%lld\n",ans);
    }
}

 

於是可以用容斥原理來求

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章