C-Sum of Suffix Sums
题目类型:签到,数学。
解题思路:题目要求输出每次操作后当前序列后缀和的和,可以发现每个ai在总和中出现i次,维护一个数组存放i*ai的前缀和即可。
AC代码:
#include<iostream>
using namespace std;
typedef long long LL;
const LL N=500010,mod=1000000007;
LL ans[N];
int idx=0;
void op(){
int t,v;
cin>>t>>v;
idx=idx-t+1;
ans[idx]=(ans[idx-1]+v*idx)%mod;
cout<<ans[idx]<<'\n';
}
int main()
{
int q;cin>>q;
while(q--){
op();
}
return 0;
}
H-World Finals
题目类型:签到。
解题思路:第一场最优排名为除lzr010506其他double-qualified的队伍都参加第二场,第二场最优排名为除lzr010506其他double-qualified的队伍都参加第二场,两个排名取最优。
AC代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
#include<utility>
using namespace std;
map<string,pair<int,int> >a,b;
int main()
{
int n;cin>>n;
pair<int,int>x1,x2;
for(int i=1;i<=n;i++){
string s;
int p,t;
cin>>s>>p>>t;
a[s]={p,t};
if(s=="lzr010506") x1={p,t};
}
int m;cin>>m;
for(int i=1;i<=m;i++){
string s;
int p,t;
cin>>s>>p>>t;
b[s]={p,t};
if(s=="lzr010506") x2={p,t};
}
int rk1=1,rk2=1;
for(auto x:a){
if(b.count(x.first)){
continue;
}
else if((x.second.first==x1.first && x.second.second<x1.second) || x.second.first>x1.first){
rk1++;
}
}
for(auto x:b){
if(a.count(x.first)){
continue;
}
else if((x.second.first==x2.first && x.second.second<x2.second) || x.second.first>x2.first){
rk2++;
}
}
cout<<min(rk1,rk2);
return 0;
}
I-Mirror Maze
题目类型:搜索。
解题思路:所有的光线都是环或链(射出边界),遍历所有的环和链,记录每个光源(不同位置不同方向共4nm个)的答案,每次询问输出即可。
AC代码:
#include<iostream>
#include<string>
#include<utility>
#include<set>
using namespace std;
typedef pair<int,int> PII;
/*
0:above
1:below
2:left
3:right
*/
const int N=1010;
char s[N][N];
int n,m;
int vis[N][N][4];
int dp[N][N][4]; //存放每个光源的答案
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
set<PII>st;
int alter(int x,int y,int d){
int nd=d;
if(s[x][y]=='|'){
if(d==2) nd=3;
else if(d==3) nd=2;
}
else if(s[x][y]=='-'){
if(d==0) nd=1;
else if(d==1) nd=0;
}
else if(s[x][y]=='/'){
if(d==0) nd=3;
else if(d==1) nd=2;
else if(d==2) nd=1;
else if(d==3) nd=0;
}
else{
if(d==0) nd=2;
else if(d==1) nd=3;
else if(d==2) nd=0;
else if(d==3) nd=1;
}
return nd;
}
void dfs(int x,int y,int d){
if(x>n || y>m || x<1 || y<1) return;
if(vis[x][y][d]==2) return;
int nd=alter(x,y,d); //经过当前镜面后的方向
vis[x][y][d]++;
dfs(x+dx[nd],y+dy[nd],nd);
vis[x][y][d]=0;
//若发生反射则加入集合st,st存放反射当前光源的镜面
if(nd!=d) st.insert({x,y});
dp[x][y][d]=st.size();
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=0;k<4;k++){
if(!dp[i][j][k]){
//处理新的光源的答案时清空st
st.clear();
dfs(i,j,k);
}
}
}
}
int q;cin>>q;
while(q--){
int u,v;
string dir;
cin>>u>>v>>dir;
int id,ans;
if(dir=="above"){
id=0;
}
else if(dir=="below"){
id=1;
}
else if(dir=="left"){
id=2;
}
else{
id=3;
}
//输入的光源位置是不反射光的,有效光源位置应该是下一个位置
ans=dp[u+dx[id]][v+dy[id]][id];
cout<<ans<<'\n';
}
return 0;
}
A-A Bit Common
题目类型:数学。
解题思路:只有最后一位为1的数按位与后才可能是1。设n个数中有i个数最后一位为1(符合要求的子序列),对于这i个数的其它位(共m-1位)中的任意一位,至少有一个数的这一位为0,则这i个数的方案数为(2^i-1)^(m-1);对于其他n-i个数,除最后一位为0外其他位可以任取,则这n-i个数的方案数位2^((m-1)*(n-i));因为符合要求的子序列和其他数位置可以任选,所以最后答案为
ans=C(n,i)*(2^i-1)^(m-1)*2^((m-1)*(n-i))%q。
AC代码:
#include<iostream>
using namespace std;
typedef long long LL;
const int N=5010;
LL n,m,q;
LL c[N][N];
LL qmi(LL a,LL b,LL q){
LL res=1;
while(b){
if(b&1) res=(res*a)%q;
b>>=1;
a=(a*a)%q;
}
return res;
}
void init(){
for(int i=0;i<N;i++){
for(int j=0;j<=i;j++){
if(!j) c[i][j]=1;
else c[i][j]=(c[i-1][j-1]+c[i-1][j])%q;
}
}
}
int main()
{
cin>>n>>m>>q;
init();
LL ans=0;
for(int i=1;i<=n;i++){
LL res=c[n][i];
res=(res*qmi(2,(n-i)*(m-1),q))%q;
res=(res*qmi(qmi(2,i,q)-1,m-1,q))%q;
ans=(ans+res)%q;
}
cout<<ans<<'\n';
return 0;
}