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);
}
}
於是可以用容斥原理來求