1.签到:https://ac.nowcoder.com/acm/contest/78807/A
AC代码:
#include<bits/stdc++.h>
using namespace std;
string a[10];
int main()
{
for(int i=0;i<6;i++) cin>>a[i];
if(a[0][3]=='.') cout<<'o';
else if(a[4][5]=='\\') cout<<'m';
else cout<<'p';
}
2.简单的博弈:https://ac.nowcoder.com/acm/contest/78807/B
AC代码:
#include<bits/stdc++.h>
using namespace std;
int t,n;
int main()
{
cin>>t;
while(t--)
{
cin>>n;
if(n%4==0) cout<<"Bong"<<endl;
else cout<<"Bing"<<endl;
}
}
3.贪心:https://ac.nowcoder.com/acm/contest/78807/C
显然,假如它到中心的时间>两边坍塌的max时间一定没有希望。
我们假设一边坍塌要m时间,另一边n(m>n)
一开始在m那一边走到终点要t1(t1<=m),在n走到终点要t2(t2<=n),那么t1+t2<=m;
我们先让n边走t2,此时m那一边坍塌了t2,即m-t2,又m-t2>=t1,因此我们可以再直接走到终点。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int main()
{
cin>>n>>m>>k;
int v1=n/2+1,v2=m/2+1;
int c1=n/2,c2=m/2;
int cnt=0;
while(k--)
{
int x,y;
scanf("%d%d",&x,&y);
int cx=abs(x-v1),cy=abs(y-v2);
if(cx+cy<max(v1,v2)) cnt++;
}
cout<<cnt;
}
4.DP的思想:https://ac.nowcoder.com/acm/contest/78807/D
我们让cnt表示前面数的选取总方案,假如此位是偶数,那么以他结尾的贡献就是cnt+1(自己)
如果是奇数那么没有贡献。
对于cnt的变化都是2*cnt+1(0的话由于不能前导还要-1)
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
long long cnt=0,sum=0;
int mod=1e9+7;
int main()
{
cin>>n>>s;
for(int i=0;i<s.size();i++)
{
if(s[i]=='0')
{
sum=(sum+cnt+1)%mod;
cnt=cnt*2%mod;
}
else if((s[i]-'0')%2)
{
cnt=(cnt*2+1)%mod;
}
else{
sum=(sum+cnt+1)%mod;
cnt=(cnt*2+1)%mod;
}
}
cout<<sum;
}
5.子序列自动机:https://ac.nowcoder.com/acm/contest/78807/E
我们用nxt[i][j]表示从i开始后到第一个j出现的位置(不包含自己)
我们再找到第一个ACCEPT以及WA的位置相减即可。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,k;
string s;
int nxt[200010][30];//从i开始后到第一个j出现的位置(不包含自己)
int cnt=0;
string ss="ACCEPT";
string sss="WA";
int findac(int pos)
{
if(s[pos]=='A')
{
for(int i=1;i<=5;i++)
{
pos=nxt[pos][ss[i]-'A'];
}
}
else
{
for(int i=0;i<=5;i++)
{
pos=nxt[pos][ss[i]-'A'];
}
}
return pos;
}
int findwa(int pos)
{
if(s[pos]=='W')
{
for(int i=1;i<=1;i++)
{
pos=nxt[pos][sss[i]-'A'];
}
}
else
{
for(int i=0;i<=1;i++)
{
pos=nxt[pos][sss[i]-'A'];
}
}
return pos;
}
int main()
{
cin>>n>>k;
cin>>s;
for(int i=0;i<=26;i++) nxt[s.size()-1][i]=n;
for(int i=0;i<26;i++) nxt[n][i]=n;
for(int i=s.size()-2;i>=0;i--)
{
for(int j=0;j<=25;j++)
{
if('A'+j==s[i+1])
{
nxt[i][j]=i+1;
}
else{
nxt[i][j]=nxt[i+1][j];
}
}
}
//cout<<findwa(1);
for(int i=0;i<s.size();i++)
{
int j1=findac(i);
int j2=findwa(i);
cnt+=max(0,j2-j1-max(0,k-6));
}
//for(int i=0;i<=s.size()-1;i++) cout<<nxt[i][0]<<" ";
cout<<cnt;
}
6.贡献法+拆位:https://ac.nowcoder.com/acm/contest/78807/F
直接贡献法枚举(i,j)复杂度n^2级别,看到异或我们就直接拆位,考虑到其大小我们枚举1--20,对于每一位t,我们考虑它的贡献,假如他是1,那么我们只考虑它前面的贡献,也就是为0的位置(组成一个(i,j)序对),至于它的大小就是2^t*(n-i+1)*v0,v0就是前面0的下标的前缀和,而它后面可以有n-i+1中选择。而对于(i,j),因为还要考虑对后面的贡献,也就再来一份。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n;
long long a[1000100];
int mod=1e9+7;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
long long ans=0;
for(int i=0;i<=20;i++)
{
long long v0=0,v1=0;
for(int j=1;j<=n;j++)
{
if((a[j]>>i)&1)
{
ans=(ans+v0*(n-j+1)%mod*(1<<i)%mod*2% mod)%mod;
v1=(v1+j)%mod;
}
else{
ans=(ans+v1*(n-j+1)%mod*(1<<i)%mod*2% mod)%mod;
v0=(v0+j)%mod;
}
}
}
cout<<ans;
}