A:http://codeforces.com/contest/1151/problem/A
枚举每4个 求变成ACTG的最小次数
#include <bits/stdc++.h>
const int M = 100000+100;
using namespace std;
char q[5]={' ','A','C','T','G'};
int ab(int a)
{
if(a<0)
return -a;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
string s;
cin>>n>>s;
int sum=0,mi=1000000,now=1000000;
for(int i=0;i+3<n;i++)
{
sum=0;
for(int j=1;j<=4;j++)
{
now=abs(s[i+j-1]-q[j]);
sum+=min(now,26-now);
}
mi=min(mi,sum);
}
cout<<mi<<endl;
// cout<<'I'-'H';
return 0;
}
//ZCTHGZDATGZCTHGZDATGZCTHGZDATGZCTHGZDATGZCTHGZDATG
B:http://codeforces.com/contest/1151/problem/B
先对每一行的第一项求异或和。
如果不等于0 说明可以。
如果等于0的话,求每一行其他数与第一个数异或和不等于0的数。
如果存在 说明可以 不存在就不行。
这里用到了异或的一个性质
即 如果 A^C==B^C==0 则A^B==0;
因为 A^B==A^B^C^C==0(自己异或自己的为0不影响异或和)
#include <bits/stdc++.h>
const int M = 100000+100;
using namespace std;
char q[5]={' ','A','C','T','G'};
int mx[507][507];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>mx[i][j];
int x=0;
for(int j=1;j<=n;j++)
x^=mx[j][1];
int posi=1,posj=1;
int flag=true;
if(x!=0)flag=false;
else
//cout<<x<<endl;
for(int i=1;i<=n;i++)
{
for(int j=2;j<=m;j++)
{
int w=mx[i][j]^mx[i][1];
if(w!=0)
{
posi=i;posj=j;
// cout<<mx[i][j]<<" == "<<mx[i][1]<<endl;
flag=false;
break;
}
}
}
if(flag)
cout<<"NIE"<<endl;
else
{
cout<<"TAK"<<endl;
for(int i=1;i<=n;i++)
{
if(i==posi)
cout<<posj<<" ";
else
cout<<1<<" ";
}
cout<<endl;
}
return 0;
}
C:http://codeforces.com/contest/1151/problem/C
如果我们知道前n个数里有几个偶数几个奇数 就能很方便的求出前n个数的和。(用等差数列)
2^0奇数 2^1偶数 2^2奇数……;
然后我们就可以利用这个从1 开始往后倍增 求出个数
然后求出前n项和
区间l,r的和就等于 solve r-solve l-1;
复杂度 Ologn
#include <bits/stdc++.h>
const int M = 100000+7;
using namespace std;
typedef long long ll;
const ll MOD =1000000000+7;
ll solve(ll n)
{
ll no=0,ne=0;
ll sum=0;
ll x=n,w=1,f=1;
while(x>0)
{
x-=w;
if(x>0)
{
if(f&1) no+=w;
else ne+=w;
}
else
{
if(f&1) no+=x+w;
else ne+=x+w;
}
f++;
w*=2;
//cout<<w<<endl;
}
// cout<<no<<" "<<ne<<endl;
sum+=no%MOD*(no%MOD);
sum+=ne%MOD*((ne+1)%MOD);
return sum%MOD;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll l,r;
cin>>l>>r;
cout<<(solve(r)%MOD-solve(l-1)%MOD+MOD)%MOD<<endl;
return 0;
}
E:http://codeforces.com/contest/1151/problem/E
直接算不好算。
我们可以从贡献的角度来考虑。
首先考虑f(l,r) 是A数组取值在l,r之间的数变成1,其他为0.然后从前往后01序列的个数。
01串出现其实就相当于前一个数不在l,r区间 当前数在;l,r区间。
所以我们对A这个序列,从前往后
如果a[i]>a[i-1],满足01串的条件是 0<a[i-1]<l<=a[i]<=r<n;
则 第i个数对01串总数的贡献是 (a[i]-a[i-1])*(n-a[i]+1) l的取值个数*r的取值个数(注意 r的取值在a[i]--n之间 包括n 所以+1)
同理求a[i]<a[i-1]的情况即可
相等 时 无贡献
#include <bits/stdc++.h>
const int M = 100000+7;
using namespace std;
typedef long long ll;
ll a[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
ll ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]>a[i-1])
ans+=(a[i]-a[i-1])*(n-a[i]+1);//
if(a[i]<a[i-1])
ans+=(a[i-1]-a[i])*a[i];
//如果相等 则无贡献
}
cout<<ans<<endl;
return 0;
}