• [NOI Online #3 提高组]


    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

  • 相关阅读:
    存储过程中执行动态Sql语句
    SqlServer新建视图
    DataGridView DataGridViewCheckBoxColumn编辑时实时触发事件
    oracle number 和sqlserver numeric的区别
    放下你的无效社交
    一个程序员眼中的北京和上海
    10+年程序员总结的20+条经验教训
    SQL collate
    SQL自定义函数split分隔字符串
    C# .NET开发Oracle数据库应用程序
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12951240.html
Copyright © 2020-2023  润新知