Preface
NOIOL的实质竟然是卡常数大赛吗,爱了爱了
话说我终于相信了这个系列的比赛难度都是蓝题了。(虽然第一场翻车翻到天上了)
PS:如果让开O2就AK了(flag),不给开就炸成100……
[NOI Online #3 提高组]水壶
正常人都知道只选一个水壶的话答案显然就是连续的(k+1)个数的和的最大值
由于没有负数所以直接前缀和即可
#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=1000005;
int n,k,a[N],pfx[N],ans;
int main()
{
freopen("kettle.in","r",stdin); freopen("kettle.out","w",stdout);
RI i; for (scanf("%d%d",&n,&k),++k,i=1;i<=n;++i)
scanf("%d",&a[i]),pfx[i]=pfx[i-1]+a[i];
for (i=1;i<=n;++i) ans=max(ans,pfx[i]-pfx[i>=k?i-k:0]);
return printf("%d",ans),0;
}
[NOI Online #3 提高组]魔法值
容易想到这种异或的题目考虑求出每个点对答案的贡献
建出原图的邻接矩阵,考虑转移的时候就是一个对(2)取余的矩阵乘法,然后这样的复杂度是(O(q imes n^3log n))
然后应该开始思考(O(q imes n^2log n))做法我们发现这个矩乘的过程可以看做拿出一行和一列(operatorname{and}),然后考虑(1)的个数的奇偶性即可
用bitset
维护行列信息,复杂度就是(O(frac{q imes n^3log n}{32}))的
然后跑一发极限数据,4.5s难受,开一发O2,2.5s显然过不了啊
不要灰心我们细细一想这题(nle 100),我拿两个ull就可以存下所有信息,所以干脆直接手写bitset
写完了跑一发1.2s就NM离谱,没事我们加上O2,700ms卡过……
PS:不要问我NOIOL可不可以手开O2
#pragma GCC optimize(3)
#include<cstdio>
#include<cstring>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
typedef unsigned long long u64;
const int N=105;
int n,m,q,x,y,cnt[65536]; long long p,ans,a[N];
inline void Set(u64 *p,CI x)
{
if (x<64) p[0]|=1ull<<x; else p[1]|=1ull<<x-64;
}
inline int Cnt(const u64& x)
{
return cnt[x&65535]^cnt[(x>>16)&65535]^cnt[(x>>32)&65535]^cnt[x>>48];
}
struct Matrix
{
int n,m; u64 h[N][2],l[N][2];
inline Matrix(CI N=0,CI M=0)
{
n=N; m=M; memset(h,0,sizeof(h)); memset(l,0,sizeof(l));
}
friend inline Matrix operator * (Matrix A,Matrix B)
{
Matrix C(A.n,B.m); for (RI i=0,j;i<C.n;++i) for (j=0;j<C.m;++j)
if (Cnt(A.h[i][0]&B.l[j][0])^Cnt(A.h[i][1]&B.l[j][1]))
Set(C.h[i],j),Set(C.l[j],i); return C;
}
friend inline Matrix operator ^ (Matrix A,long long p)
{
Matrix T(A.n,A.m); for (RI i=0;i<T.n;++i) Set(T.h[i],i),Set(T.l[i],i);
for (;p;p>>=1,A=A*A) if (p&1) T=T*A; return T;
}
};
int main()
{
freopen("magic.in","r",stdin); freopen("magic.out","w",stdout);
RI i; scanf("%d%d%d",&n,&m,&q); Matrix G(n,n);
for (i=1;i<65536;++i) cnt[i]=cnt[i>>1]^(i&1);
for (i=0;i<n;++i) scanf("%lld",&a[i]); for (i=1;i<=m;++i)
scanf("%d%d",&x,&y),--x,--y,Set(G.h[x],y),Set(G.l[y],x),Set(G.h[y],x),Set(G.l[x],y);
while (q--)
{
scanf("%lld",&p); Matrix T=G^p; for (ans=i=0;i<n;++i)
if (T.h[i][0]&1) ans^=a[i]; printf("%lld
",ans);
}
return 0;
}
[NOI Online #3 提高组]优秀子序列
这题和[CTSC2017]吉夫特很像,都是标算(O(2^n imes n^2))然后被(O(3^n))艹过
首先显然考虑求出每个数出现的次数,然后考虑选出的子序列的性质,显然是不能在某一个二进制位上有两个及以上的(1)
因此子序列的和就是(a_i)级别的了,我们考虑直接DP维护它,设(f_i)表示子序列的和为(i)的方案数
然后转移的时候因为同一位上不能有多的(1),因此转移就是枚举子集(j),这个是(O(3^n))的
然后注意一下转移的时候判一下(j>ioperatorname{xor}j)防止重复转移,然后直接算答案即可
PS:注意(0)的贡献要单独算,初值要赋成(2^{c_0})
PPS:不开O2过不去233……
PPPS:听说有julao写了FWT+EXP的,然后还没暴力快的说……
#pragma GCC optimize(3)
#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=262144,mod=1e9+7;
int n,x,c[N],f[N],phi[N+5],prime[N+5],cnt,ans; bool vis[N+5];
#define P(x) prime[x]
inline void init(CI n=N)
{
RI i,j; for (vis[1]=phi[1]=1,i=2;i<=n;++i)
{
if (!vis[i]) prime[++cnt]=i,phi[i]=i-1;
for (j=1;j<=cnt&&i*P(j)<=n;++j)
{
vis[i*P(j)]=1; if (i%P(j)) phi[i*P(j)]=phi[i]*(P(j)-1);
else phi[i*P(j)]=phi[i]*P(j);
}
}
}
#undef P
inline void inc(int& x,CI y)
{
if ((x+=y)>=mod) x-=mod;
}
int main()
{
freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout);
RI i,j; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&x),++c[x];
for (f[0]=i=1;i<=c[0];++i) inc(f[0],f[0]);
for (i=1;i<N;++i) for (j=i;;j=(j-1)&i)
{
if (j>(i^j)) inc(f[i],1LL*c[j]*f[i^j]%mod); if (!j) break;
}
for (init(),i=0;i<N;++i) inc(ans,1LL*phi[i+1]*f[i]%mod);
return printf("%d",ans),0;
}
Postscript
CCF送温暖,下次还要继续呦
5/27Upt:woc就我被卡成了290……kel