D.
题意:给你一个颜色序列,把相邻颜色相同的一坨看做一个块,我们可以改变一个块的颜色,然后显然可以合并相邻的颜色块,问最终合并成一个块需要几步
解析:显然一个连续的区间最终变成的颜色就是最左边或者最右边的颜色,所以直接dp即可
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5010;
int f[MAXN][MAXN][2];
int n,a[MAXN];
int solve(int l,int r,int k)
{
if (f[l][r][k]!=-1)
return f[l][r][k];
if (k==0) {
f[l][r][k]=min(solve(l+1,r,0)+(a[l+1]==a[l]?0:1),solve(l+1,r,1)+(a[r]==a[l]?0:1));
}
else f[l][r][k]=min(solve(l,r-1,0)+(a[l]==a[r]?0:1),solve(l,r-1,1)+(a[r]==a[r-1]?0:1));
return f[l][r][k];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(f,255,sizeof(f));
for (int i=1;i<=n;i++) f[i][i][0]=f[i][i][1]=0;
printf("%d\n",min(solve(1,n,0),solve(1,n,1)));
}
E.
题目描述:这是一道交互题,你知道序列的长度,且这个数列是一个打乱的等差数列,你有两种询问,一种是询问数列中是否有大于x的数,第二种是询问序列中第x个数是什么,然后让你确定这个数列
题目解析:显然我们可以经过log1e9次操作确定这个序列的最大数,然后我们问这个等差d很难确定,由于这个序列是被打乱的,
所以我们只能随机一些位置,那么从而通过这样的方式来得到d(直接gcd即可)
显然这个随机是比较重要的,然后我的随机函数竟然比不上10~20遍的random_shuffle(晕)
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
int n,sum;
int a[100],b[1000010];
int ans,d,x,len;
void s(int l,int r)
{
if (l==r) {
ans=l; return;
}
else {
int mid=(l+r)/2;
int x;
cout << '>' << ' ' << mid << endl;
sum++;
fflush(stdout);
cin >> x;
if (x==0) s(l,mid); else s(mid+1,r);
}
}
int gcd(int x,int y)
{
if (!x||!y) return x+y;
int z=x%y;
while (z) {
x=y; y=z; z=x%y;
}
return y;
}
int main(){
scanf("%d",&n);
s(1,inf);
for (int i=1;i<=n;i++) b[i]=i;
for (int i=1;i<=20;i++) random_shuffle(b+1,b+n+1);
srand(time(NULL));
for (int i=1;i<=min(60-sum,n);i++)
{
cout << '?' << ' ' << b[i] << endl;
fflush(stdout);
cin >> a[++len];
}
sort(a+1,a+len+1);
for (int i=1;i<len;i++) d=gcd(d,a[i+1]-a[i]);
int x1=ans-(n-1)*d;
cout << '!' << ' ' << x1 << ' ' << d << endl;
}
F.
题意:你有一个长度为n的序列a,而且你有q次操作,操作分为两种:第一中是给区间[l,r]中的数乘上x,第二种是询问区间[l,r]中的所有的数的积的欧拉函数值,modulo 1e9+7
解析:题目中有个性质就是不管是x,还是原来的ai他们都不会超过300,然后打表一看就发现300以内的质数的个数为62,所以我们可以用二进制来维护每一个质数是否出现,所以就是简单的线段树区间乘,区间或(为什么可以这么做?因为欧拉函数的计算公式)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod=1e9+7;
const int MAXN=4e5+10;
struct node{
LL po1,po2,s,la;
}tree[MAXN<<2];
int n,q,len,l,r,x;
int prime[MAXN],a[MAXN];
LL w[MAXN],b[MAXN],la;
char s[10];
LL ksm(LL x,LL y)
{
LL ans=1;
for (;y;y>>=1,x=(x*x)%mod) if (y&1) ans=(ans*x)%mod;
return ans;
}
LL mul(LL x,LL y)
{
return (x*y)%mod;
}
void init()
{
for (int i=2;i<=300;i++)
{
bool p=1;
for (int j=2;j*j<=i;j++)
if (i%j==0) {
p=0; break;
}
if (p) prime[++len]=i;
}
for (int i=1;i<=len;i++) w[i]=mul((prime[i]-1),(ksm(prime[i],mod-2)));
}
void update(int k)
{
tree[k].s=mul(tree[k<<1].s,tree[k<<1|1].s);
tree[k].la=(tree[k<<1].la|tree[k<<1|1].la);
}
void build(int l,int r,int k)
{
tree[k].po1=1;
if (l==r) {
tree[k].s=a[l]; tree[k].la=b[l];
}
else {
int mid=(l+r)/2;
build(l,mid,k<<1); build(mid+1,r,k<<1|1);
update(k);
}
}
LL pan(int x)
{
LL ans=0;
for (int i=1;i<=len;i++)
if (x%prime[i]==0)
ans|=(1ll<<(i-1));
return ans;
}
void pushdown(int k,int l1,int l2)
{
if (tree[k].po1!=1)
{
tree[k<<1].po1=mul(tree[k].po1,tree[k<<1].po1); tree[k<<1].s=mul(tree[k<<1].s,ksm(tree[k].po1,l1));
tree[k<<1|1].po1=mul(tree[k<<1|1].po1,tree[k].po1); tree[k<<1|1].s=mul(tree[k<<1|1].s,ksm(tree[k].po1,l2));
tree[k].po1=1;
}
if (tree[k].po2)
{
tree[k<<1].po2|=tree[k].po2; tree[k<<1].la|=tree[k].po2;
tree[k<<1|1].po2|=tree[k].po2; tree[k<<1|1].la|=tree[k].po2;
tree[k].po2=0;
}
}
LL find_lalala(int l,int r,int k,int ll,int rr)
{
if (l==ll&&r==rr)
{
la|=tree[k].la;
return tree[k].s;
}
else {
int mid=(l+r)/2;
pushdown(k,mid-l+1,r-mid);
if (rr<=mid) return find_lalala(l,mid,k<<1,ll,rr);
else if (ll>mid) return find_lalala(mid+1,r,k<<1|1,ll,rr);
else return mul(find_lalala(l,mid,k<<1,ll,mid),find_lalala(mid+1,r,k<<1|1,mid+1,rr));
update(k);
}
}
LL findans(int l,int r)
{
la=0;
LL ans=find_lalala(1,n,1,l,r);
for (int i=1;i<=len;i++)
{
if (la&1) {
ans=mul(ans,w[i]);
}
la>>=1;
}
return ans;
}
void change(int l,int r,int k,int ll,int rr,LL x,LL y)
{
if (l==ll&&r==rr)
{
LL s1=ksm(x,r-l+1);
tree[k].s=(tree[k].s*s1)%mod;
tree[k].po1=(tree[k].po1*x)%mod;
tree[k].la|=y;
tree[k].po2|=y;
}
else {
int mid=(l+r)/2;
pushdown(k,mid-l+1,r-mid);
if (rr<=mid) change(l,mid,k<<1,ll,rr,x,y);
else if (ll>mid) change(mid+1,r,k<<1|1,ll,rr,x,y);
else {
change(l,mid,k<<1,ll,mid,x,y); change(mid+1,r,k<<1|1,mid+1,rr,x,y);
}
update(k);
}
}
int main()
{
scanf("%d%d",&n,&q);
init();
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
for (int i=1;i<=n;i++) b[i]=pan(a[i]);
build(1,n,1);
for (int i=1;i<=q;i++)
{
scanf("%s",s);
if (s[0]=='T') {
scanf("%d%d",&l,&r); printf("%lld\n",findans(l,r));
}
else {
scanf("%d%d%d",&l,&r,&x); change(1,n,1,l,r,x,pan(x));
}
}
}