Codeforces Round #757 (Div. 2) 题解

116 阅读1分钟

比赛链接

C

思路

先考虑如果已知一个数组,如何求出它的cozinesscoziness。考虑每一个二进制位的贡献,假设有mm个数字的二进制下某一位为11,那么要想对答案产生贡献,就只能从这mm个数字中选奇数个,Cm1+Cm3+=2m1C^1_m+C^3_m+\cdots=2^{m-1},剩下的nmn-m个数字可以随便选,就有2nm2^{n-m}种选择,乘起来就是2n12^{n-1},发现与mm无关,所以对于某一位只要存在至少一个数字为11,就可以产生2n12^{n-1}的贡献。代码写复杂了贴一下别人的。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int Mod=1e9+7;
int t,l,r,n,x,m,ans;
int ksm(int a, int n, int m) {
	int ans = 1;
	while(n) {
		if(n&1) {
			ans = (ans * a) % m;
		}
		a = (a * a) % m;
		n >>= 1;
	}
	return ans;
}
signed main() {
	cin>>t;
	while(t--) {
		cin>>n>>m;
		ans=0;
		for(int i=1; i<=m; i++) {
			cin>>l>>r>>x;
			ans|=x;
		}
		ans=(ans*ksm(2,n-1,Mod))%Mod;
		cout<<ans<<endl;
	}
}

D1

思路

DP

随着右端点增大,最大公因数必定是减小的,设dpidp_i为最后一个大于11gcdgcdii时能够产生的最大答案。这种情况显然只能从ii的倍数转移过来,设这个倍数为jj,再设原数组中数字kk的倍数的个数为tkt_k,那么状态转移方程就是dpi=max(dpj+i(˙titj))dp_i=max(dp_j+i\dot (t_i-t_j))。复杂度为ni=O(logN)\sum\frac{n}{i}=O(\log N)

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
    int __=0;
    _=0;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            __=1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        _=_*10+ch-48;
        ch=getchar();
    }
    _=__?-_:_;
    read(oth...);
}
template <typename T>
void Out(T _)
{
    if(_<0)
    {
        putchar('-');
        _=-_;
    }
    if(_>=10)
       Out(_/10);
    putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
	Out(_);
	putchar('\n');
	OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
	Out(_);
	putchar(' ');
	op(oth...);
}
/*#################################*/
const ll N=1E5+10,M=5E6+10;
ll n,ans,maxi;
ll a[N],t[M],dp[M];
int main()
{
	read(n);
	rep(i,1,n)
	{
		read(a[i]);
		maxi=max(maxi,a[i]);
		ll lim=sqrt(a[i]);
		rep(div,1,lim)
		{
			if(a[i]%div==0)
			{
				++t[div];
				ll tmp=a[i]/div;
				if(tmp!=div)
					++t[tmp];
			}
		}
	}
	for(int i=maxi;i>=1;--i)
	{
		dp[i]=t[i]*i;
		for(int j=i+i;j<=maxi;j+=i)
		{
			dp[i]=max(dp[i],dp[j]+i*(t[i]-t[j]));
		}
		ans=max(ans,dp[i]);
	}
	OP(ans);
}