题目链接:戳我
好久没有写CF了(实际上好久没有动脑子了),实在是惨淡至极。这几天打算每天都开virtual contest qwq......
A
注意情况的分类讨论qwq
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100
using namespace std;
int n,ans=0x3f3f3f3f;
char s[MAXN];
inline int dis(char from,char to)
{
int cur_ans=0x3f3f3f3f;
if(to>from)
{
cur_ans=min(cur_ans,to-from);
cur_ans=min(cur_ans,from-'A'+'Z'-to+1);
}
else
{
cur_ans=min(cur_ans,from-to);
cur_ans=min(cur_ans,'Z'-from+to-'A'+1);
}
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i+3<=n;i++)
{
int cur_ans=0;
cur_ans+=dis(s[i],'A');
cur_ans+=dis(s[i+1],'C');
cur_ans+=dis(s[i+2],'T');
cur_ans+=dis(s[i+3],'G');
ans=min(ans,cur_ans);
}
printf("%d
",ans);
return 0;
}
B
正解好像是DP......但是异或等于0的概率其实很小,而且还有special judge QAQ完全可以用随机化算法对吧!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<ctime>
#define MAXN 2048
using namespace std;
int n,m,cnt;
int a[MAXN][MAXN];
struct Node{int x,y;};
vector<Node>vec;
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
srand(time(0));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
int ans=0;
for(int i=1;i<=n;i++)
{
int cur=rand()%m+1;
vec.push_back((Node){i,cur});
ans^=a[i][cur];
}
while(ans==0&&cnt<=10000000)
{
int cur=rand()%vec.size();
ans^=a[vec[cur].x][vec[cur].y];
vec[cur].y=rand()%m+1;
ans^=a[vec[cur].x][vec[cur].y];
cnt++;
}
if(ans==0) printf("NIE
");
else
{
printf("TAK
");
for(int i=0;i<vec.size();i++)
printf("%d ",vec[i].y);
}
// cout<<(double)clock()/CLOCKS_PER_SEC<<endl;
return 0;
}
C
两个long long相乘之前一定要记得取模
区间问题不好处理,但是从1开始就比较容易的问题可以用差分解决
1,3,5,7这种奇数序列的前缀和为(i^2),2,4,6,8这种偶数序列的前缀和为(i^2+i)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define mod 1000000007
using namespace std;
ll l,r;
inline ll sum(ll x)
{
ll last=0,cnt1=0,cnt2=0,ans=0;
for(ll i=1,j=1;last<x;i<<=1,j++)
{
// printf("i=%lld last=%lld
",i,last);
if(j&1)
{
if(last+i<=x) cnt1+=i,last+=i;
else cnt1+=(x-last),last=x;
}
else
{
if(last+i<=x) cnt2+=i,last+=i;
else cnt2+=(x-last),last=x;
}
// printf("cnt1=%lld cnt2=%lld
",cnt1,cnt2);
}
// cout<<cnt1<<" "<<cnt2<<endl;
cnt1%=mod,cnt2%=mod;
ans=(ans+cnt1*cnt1%mod)%mod;
ans=(ans+cnt2*cnt2%mod)%mod;
ans=(ans+cnt2%mod)%mod;
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
cin>>l>>r;
cout<<((sum(r)-sum(l-1))%mod+mod)%mod<<endl;
return 0;
}
D
把式子展开一下就行了,是一个定值+(sum a[i]-b[i])
然后贪心一下就行了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define MAXN 100010
using namespace std;
int n;
struct Node{int a,b,sum,id;}node[MAXN];
inline bool cmp(struct Node x,struct Node y)
{
return x.sum>y.sum;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&node[i].a,&node[i].b);
node[i].sum=node[i].a-node[i].b;
node[i].id=i;
}
sort(&node[1],&node[n+1],cmp);
long long ans=0;
for(int i=1;i<=n;i++)
{
ans+=1ll*node[i].b*n-node[i].a;
ans+=1ll*i*node[i].sum;
}
cout<<ans<<endl;
return 0;
}
E
这个题都说简单可是我还是没有做出来。。。。
题意:每次保留值为[l,r]区间的点,问(sum_{l=1}sum_{r=l+1})的联通块的个数。
因为是一条链,所以我们可以考虑每个点的贡献。
对于每个点,假设它是连通块里面编号最大的QAQ,那么就一定有编号i+1不在该联通块里。
如果a[i]>a[i+1],贡献为(a[i]-a[i+1]*(n-a[i]+1))
如果a[i]<=a[i+1],贡献为((a[i+1]-a[i])*a[i])
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
int n;
long long ans;
long long a[MAXN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++)
{
if(a[i]<=a[i+1]) ans+=1ll*(a[i+1]-a[i])*a[i];
else ans+=1ll*(a[i]-a[i+1])*(n-a[i]+1);
}
cout<<ans+1ll*(n-a[n]+1)*a[n]<<endl;
return 0;
}
F
题目大意:给你一个长度为N的数列,里面只有0或者1。可以操作K次,每次交换两个数。询问K次之后的数列中,为不下降序列的概率为多少?
对1e9+7取模。
不下降序列只有一种,就是前(0的个数,这里设为m)位置为0,后面的为1。
一个神奇的DP(好吧也不神奇),就是设(dp[i][j])表示第i次操作后,前m个位置中有j个1的方案数。
这样子我们就可以递推了。
前m个位置中有m-j个0,j个1;后面有j个0,n-m-j个1.
递推这个样子写:
for(int i=1;i<=k;i++)
{
for(int j=0;j<=min(m,n-m);j++)
{
if(j+1<=min(m,n-m))
dp[i][j+1]=(dp[i][j+1]+1ll*dp[i-1][j]*(m-j)%mod*(n-m-j)%mod)%mod;
//0<-->1
dp[i][j]=(dp[i][j]+1ll*dp[i-1][j]*(m-j)%mod*j%mod)%mod;
//0<-->0
dp[i][j]=(dp[i][j]+1ll*dp[i-1][j]*j%mod*(n-m-j)%mod)%mod;
//1<-->1
dp[i][j]=(dp[i][j]+(1ll*dp[i-1][j]*(m-1)*m/2)%mod)%mod;
//前m中交换
dp[i][j]=(dp[i][j]+(1ll*dp[i-1][j]*(n-m-1)*(n-m)/2)%mod)%mod;
//后n-m个中交换
if(j-1>=0)
dp[i][j-1]=(dp[i][j-1]+1ll*dp[i-1][j]*j%mod*j%mod)%mod;
//1<-->0
}
}
但是这个样子会T......
所以要加一个矩阵快速幂QAQ(注意计算后一定要返回值啊QAQ)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 110
#define mod 1000000007
using namespace std;
int n,k,m,nn;
int a[MAXN],dp[MAXN][MAXN];
struct Node{int t[MAXN][MAXN];}init,ans;
inline int fpow(int x,int y)
{
int cur_ans=1;
while(y)
{
if(y&1) cur_ans=1ll*cur_ans*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return cur_ans;
}
inline Node calc(Node x,Node y)
{
Node cur_ans;
for(int i=0;i<=nn;i++)
for(int j=0;j<=nn;j++)
cur_ans.t[i][j]=0;
for(int i=0;i<=nn;i++)
for(int j=0;j<=nn;j++)
for(int p=0;p<=nn;p++)
{
cur_ans.t[i][j]=(cur_ans.t[i][j]+1ll*x.t[i][p]*y.t[p][j]%mod)%mod;
// printf("cur[%d][%d]=%d
",i,j,cur_ans.t[i][j]);
}
return cur_ans;
}
inline Node solve(Node x,int y)
{
Node cur_ans;
for(int i=0;i<=nn;i++)
for(int j=0;j<=nn;j++)
cur_ans.t[i][j]=0;
for(int i=0;i<=nn;i++) cur_ans.t[i][i]=1;
while(y)
{
if(y&1) cur_ans=calc(cur_ans,x);
x=calc(x,x);
y>>=1;
}
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
cin>>n>>k;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==0) m++;
}
int cur=0;
for(int i=1;i<=m;i++) if(a[i]==1) cur++;
int c1=(1ll*(m-1)*m/2)%mod;
int c2=(1ll*(n-m-1)*(n-m)/2)%mod;
nn=min(n-m,m);
for(int i=0;i<=nn;i++)
{
init.t[i][i]=(init.t[i][i]+(c1+c2)%mod)%mod;
init.t[i][i]=(init.t[i][i]+(1ll*(m-i)*i)%mod)%mod;
init.t[i][i]=(init.t[i][i]+(1ll*(n-m-i)*i%mod))%mod;
if(i+1<=nn)
init.t[i][i+1]=(init.t[i][i+1]+1ll*(m-i)*(n-m-i)%mod)%mod;
if(i-1>=0)
init.t[i][i-1]=(init.t[i][i-1]+1ll*i*i%mod)%mod;
}
// for(int i=0;i<=nn;i++)
// {
// for(int j=0;j<=nn;j++)
// cout<<init.t[i][j]<<" ";
// cout<<endl;
// }
init=solve(init,k);
ans.t[0][cur]=1;
ans=calc(ans,init);
int fn=1ll*fpow(fpow(n*(n-1)/2,k),mod-2)%mod;
cout<<1ll*ans.t[0][0]*fn%mod<<endl;
return 0;
}