C
思路
先考虑如果已知一个数组,如何求出它的。考虑每一个二进制位的贡献,假设有个数字的二进制下某一位为,那么要想对答案产生贡献,就只能从这个数字中选奇数个,,剩下的个数字可以随便选,就有种选择,乘起来就是,发现与无关,所以对于某一位只要存在至少一个数字为,就可以产生的贡献。代码写复杂了贴一下别人的。
代码
#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
随着右端点增大,最大公因数必定是减小的,设为最后一个大于的为时能够产生的最大答案。这种情况显然只能从的倍数转移过来,设这个倍数为,再设原数组中数字的倍数的个数为,那么状态转移方程就是。复杂度为。
代码
#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);
}