1. Codeforces Round #475
C. Alternating System: s是一个以k为周期的字符串。计算:

显然就是先算出前k个的和然后通过周期构造一个等比数列了。。。
这个模数不是通常的1e9+7而是1e9+9,cf也十分贴心地加了一句提示:
Note that the modulo is unusual!
然而窝当时猛的一激灵:嗯???这题模数是个合数??果然cf心机婊
然后冷静分析了一波模合数下的逆元怎么搞。。然而不知道什么地方写崩了wa了15发于是心态爆炸睡觉去了。。
第二天再一看题。。woc原来1e9+9也是素数啊。。。。
#include<bits/stdc++.h>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 1000000009;
ll n,k;
ll a,b;
char s[maxn];
ll mi(ll a,ll x)
{
ll res=1,tmp=a;
while(x)
{
if(x&1)res=res*tmp%mod;
x>>=1;
tmp=tmp*tmp%mod;
}
return res;
}
ll inv(ll x)
{
return mi(x,mod-2);
}
int main()
{
scanf("%I64d%I64d%I64d%I64d",&n,&a,&b,&k);
scanf("%s",s);
ll tmp=0;
for(int i=0;i<k;i++)
{
//ll cur=(mi(a,n-i)*mi(b,i))%mod;
ll vis;
if(s[i]=='+')vis=1;
else vis=-1;
tmp+=((mi(a,n-i)*mi(b,i)%mod)*vis+mod)%mod;
tmp%=mod;
}
ll num=(n+1)/k;
ll q=mi(b*inv(a)%mod,k);
//cout<<q<<endl;
if(q==1)
{
cout<<(tmp*num)%mod<<endl;
return 0;
}
ll up=(mi(q,num)-1+mod)%mod;
ll down=(q-1+mod)%mod;
ll ans=tmp*up%mod*inv(down)%mod;
printf("%I64d\n",ans);
return 0;
}
2. Codeforces Round #476
C. Greedy Arkady:一群人轮流分糖吃,每个人每次拿到的糖数有限制,问第一个人最多能拿到多少块糖。
题解:枚举分糖的次数,那么最大的情况就是分完若干轮之后刚好在第一个人处分完,即(i-1)kx+x<=n。
也就是x=n/(ki-k+1)。如果x大于m,要将x变成m。但这时候要判断一下按照现在的方案第一个人还能否分到i次糖。
#include<bits/stdc++.h>
#define maxn 10050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
ll n,m,k;
int d;
ll Max(ll a,ll b){return a>b?a:b;}
int main()
{
scanf("%I64d%I64d%I64d%d",&n,&k,&m,&d);
ll ans=0;
for(int i=1;i<=d;i++)
{
ll tmp=n/((i-1)*k+1);
if(tmp==0)break;
if(tmp>m)tmp=m;
if(n/(k*tmp)+((n%(k*tmp))>=tmp?1:0)!=i)
continue;
ans=Max(ans,tmp*i);
}
printf("%I64d\n",ans);
return 0;
}
D. Single-use Stones: 青蛙最远可以跳l的距离,在离河岸为i的地方有ai个石头,每个石头能被踩两次,问最多有多少只青蛙可以调到河对岸。
题解:能跳过多少只青蛙, 是由石头数目的最小值决定的。因此答案就是每一个(i,i+l)中石头数目的最小值。
#include<bits/stdc++.h>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,k;
ll a[maxn];
ll sum[maxn];
ll Min(ll a,ll b){return a<b?a:b;}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)
{
scanf("%I64d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
ll ans=INF;
for(int i=n-1;i>=k;i--)
ans=Min(ans,sum[i]-sum[i-k]);
printf("%I64d\n",ans);
return 0;
}
3. Educational Codeforces Round #43
C. Nested Segments: 给出若干个区间,问是否存在两个不同的区间使得其中一个区间是另一个的子集。
题解:基本上就是暴力各种剪枝了吧。。
将区间按照先左端点递增再右端点递增的顺序排序,并且预处理出从每一个区间到最后一个区间的最小的右端点值。
当i和j区间不符合条件时,如果j右侧最小的右端点都大于i的右端点的话,就不需要继续。当多个i区间左端点相同时,直接跳到这些区间中的最后一个即右端点最大的区间。
#include<bits/stdc++.h>
#define maxn 400050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n;
int a[maxn];
struct node
{
int l,r;
int id;
}e[maxn];
bool cmp(node a,node b)
{
if(a.l!=b.l)return a.l<b.l;
return a.r<b.r;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&e[i].l,&e[i].r);
e[i].id=i+1;
}
sort(e,e+n,cmp);
a[n-1]=e[n-1].r;
for(int i=n-2;i>=0;i--)
{
a[i]=min(a[i+1],e[i].r);
}
for(int i=0;i<n;i++)
{
int k=i+1,t=i;
while(k<n&&e[k].l==e[i].l)k++;
//i=k-1;
if(i!=k-1)
{
printf("%d %d\n",e[i].id,e[k-1].id);
return 0;
}
i=k-1;
for(int j=k;j<n;)
{
if(e[j].l>e[i].r)break;
if(e[j].r<=e[i].r)
{
printf("%d %d\n",e[j].id,e[i].id);
return 0;
}
else
{
if(a[j]>e[i].r)break;
int tmp=j+1;
while(tmp<n&&e[i].r<e[tmp].r&&e[tmp].l<=e[i].r)
{
//if(e[tmp].l>e[i].r)
tmp++;
}
j=tmp;
}
}
}
printf("-1 -1\n");
return 0;
}
4. Codeforces Round #478
D. Ghosts: #$%^&*%$#$%^&*
题解:经过一系列xjb推导,会碰撞的是axi-yi=axj-yj且速度向量不平行的幽灵。
#include<bits/stdc++.h>
#define maxn 200050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n;
ll a,b,x,vx,vy;
map< ll,ll >mo;
map< ll,ll >::iterator it;
map< pair<ll,ll>,ll >ex;
map< pair<ll,ll>,ll >::iterator ti;
int main()
{
scanf("%d%I64d%I64d",&n,&a,&b);
for(int i=0;i<n;i++)
{
scanf("%I64d%I64d%I64d",&x,&vx,&vy);
mo[vy-a*vx]++;
ex[make_pair(vx,vy)]++;
}
ll ans=0;
for(it=mo.begin();it!=mo.end();it++)
{
ll tmp=it->second;
ans+=tmp*(tmp-1);
}
for(ti=ex.begin();ti!=ex.end();ti++)
{
ll tmp=ti->second;
ans-=tmp*(tmp-1);
}
printf("%I64d\n",ans);
return 0;
}