版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82831285
Enlarge GCD
对于所有质数分开考虑,删除质数的指数最小的那几个数。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=3e5+50, L=2e7+50;
int n,pt,pr[L],npr[L],mnpr[L];
map <pair<int,int>,int> S;
typedef map <pair<int,int>,int> ::iterator it;
inline it nxt(it t) {return (++t);}
inline void sieve() {
for(int i=2;i<L;i++) {
if(!npr[i]) {pr[++pt]=i; mnpr[i]=i;}
for(int j=1;j<=pt;j++) {
long long k=1ll*i*pr[j];
if(k>=L) break;
npr[k]=1;
mnpr[k]=(i%pr[j]) ? pr[j] : mnpr[i];
if(!(i%pr[j])) break;
}
}
}
int main() {
sieve(); n=rd();
for(int i=1;i<=n;i++) {
int val=rd();
while(val!=1) {
int t=mnpr[val], c=0;
while(!(val%t)) val/=t, ++c;
S[pair <int,int> (t,c)]++;
}
}
int ans=n+1;
for(it l=S.begin(),r;l!=S.end();l=r) {
r=l; int cnt=0;
while(r!=S.end() && r->first.first==l->first.first) {cnt+=r->second; ++r;}
if(l!=r || (l==r && cnt!=n)) {
int mx=(cnt==n) ? l->second : (n-cnt);
ans=min(ans,mx);
}
}
if(ans>=n) cout<<-1<<'\n';
else cout<<ans<<'\n';
}
Little C Loves 3 II
特判一下比较小的情况,其他答案是 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int tr[5][5]={ {0,0,0,2,4},
{0,0,4,8,10},
{0,4,8,12,14},
{2,8,12,16,18},
{4,10,14,18,24}};
int main() {
int n,m;
cin>>n>>m;
if(n<m) swap(n,m);
long long ans=0;
if(m==1) {
ans+=n/6*6; n%=6;
ans+=tr[0][n-1];
} else if(n%4==0 || m%4==0) {
ans=(long long)n*m;
} else if(n%6==0 || m%6==0) {
ans=(long long)n*m;
} else if(n<=5 && m<=5) {
ans=tr[n-1][m-1];
} else {
if(n==7 && m==2) ans=12;
else ans=(long long)n*m/2*2;
}
cout<<ans<<'\n';
}
Region Separation
显然如果固定每部分的值,划分方案是一定的。
一个值 能被划分出来当且仅当有 个子树 。 一个值也能进一步划分为 。
枚举倍数,时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e6+50, mod=1e9+7;
inline void add(int &x,int y) {x=(x+y>=mod) ? (x+y-mod) : (x+y);}
int n,p[N],g[N],f[N];
LL a[N];
int main() {
n=rd();
for(int i=1;i<=n;i++) a[i]=rd();
for(int i=2;i<=n;i++) p[i]=rd();
for(int i=n;i>1;i--) a[p[i]]+=a[i];
for(int i=1;i<=n;i++) {
LL t=a[1]/__gcd(a[1],a[i]);
if(t<=n) ++g[t];
}
for(int i=n;i>=1;i--) for(int j=2*i;j<=n;j+=i) g[j]+=g[i];
for(int i=n;i>=1;i--) if(g[i]>=i) {
f[i]=1;
for(int j=2*i;j<=n;j+=i) add(f[i],f[j]);
}
cout<<f[1]<<'\n';
}
Intervals of Intervals
对于每个 处理出每个 的答案(差分后只有 )个。 然后二分第 大 检查即可。 时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef map <int,int> ::iterator it_m;
typedef pair <int,int> pii;
typedef pair <LL,LL> pLL;
#define X first
#define Y second
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=3e5+50;
int n,k,a[N],b[N],d[N],val[N];
vector <pii> det[N];
map <int,int> s;
inline it_m nxt(it_m it) {return ++it;}
inline void split(int p) {
it_m it=--s.upper_bound(p);
if(it->X!=p) s[p]=it->Y;
}
inline pLL check(int v) {
for(int i=1;i<=n+1;i++) d[i]=0;
LL cnt=0, sum=0;
LL nowc=0, nows=0;
for(int r=1,l=1;r<=n;++r) {
for(auto j:det[r]) {
d[j.X]+=j.Y;
if(j.X<=l) nowc+=j.Y, nows+=(LL)(l-j.X)*j.Y;
}
while(nowc>v) {
nows+=nowc;
nowc+=d[++l];
}
cnt+=(l-1); sum+=nows;
}
return pLL(cnt,sum);
}
int main() {
n=rd(), k=rd();
s[0]=0; s[1e9+1]=0;
for(int i=1;i<=n;i++) {
int l=rd()+1, r=rd();
a[i]=l; b[i]=r;
split(l); split(r+1);
for(it_m it=s.lower_bound(l);it->first<=r;) {
it_m tp=nxt(it);
det[i].push_back(pii(it->Y+1,nxt(it)->X-it->X));
s.erase(it); it=tp;
} det[i].push_back(pii(i+1,-(r-l+1)));
s[l]=i;
}
int l=0, r=1e9, lst;
pLL ans;
while(l<=r) {
int mid=(l+r)>>1;
pLL t=check(mid);
if(t.X<k) lst=mid, ans=t, r=mid-1;
else l=mid+1;
}
cout<<ans.Y+(LL)(k-ans.X)*lst;
}
Little C Loves 3 III
我们可以把 表示为 的形式,然后只需要fmt后求 。
注意到 ,直接用64位整数运算即可。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int RLEN=2<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=(1<<21)+50;
int n,m;
char A[N],B[N];
ULL a[N],b[N];
#define bc __builtin_popcount
inline void fmt(ULL *t) {
for(int i=1;i<m;i<<=1)
for(int j=0;j<m;j++) if(i&j)
t[j]+=t[i^j];
}
inline void dfmt(ULL *t) {
for(int i=1;i<m;i<<=1)
for(int j=0;j<m;j++) if(i&j)
t[j]-=t[i^j];
}
int main() {
scanf("%d%s%s",&n,A,B);
m=1<<n;
for(int i=0;i<m;i++) a[i]=(A[i]-'0')*(1ull<<(2*bc(i))), b[i]=(B[i]-'0')*(1ull<<(2*bc(i)));
fmt(a); fmt(b);
for(int i=0;i<m;i++) b[i]=a[i]*b[i];
dfmt(b);
for(int i=0;i<m;i++) putchar('0'+((b[i]>>(2*bc(i)))&3));
}