A九峰与签到题
签到题,然而wa5。保证任意时刻的都大于等于50%,才能算做签到题。
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
void solve()
{
int t;
cin>>t;
while(t--){
}
}
struct node{
int ac,fail,success,submit;
}a[25];
int main() {
//solve();
int n,m,x;
string op;
cin>>m>>n;
for(int i=0;i<m;i++){
cin>>x>>op;
if(op=="AC")a[x].ac++;
else a[x].fail++;
a[x].submit=1;
double score=1.0*a[x].ac/(1.0*a[x].ac+1.0*a[x].fail);
if(score>=0.5){
a[x].success++;
}
}
bool flag=false;
for(int i=1;i<=n;i++){
if(a[i].submit==0){
continue;
}
if(a[i].success==a[i].ac+a[i].fail){
cout<<i<<' ';flag=true;
}
}
if(!flag)cout<<"-1";
cout<<"\n";
return 0;
}
/*
3 2
1 AC
1 UNAC
1 UNAC
*/
B武辰延的字符串
给你两个串s和t。对于字符串前缀si+sj= t i + j t_{i+j} ti+j。寻找有多少个这样的组合。
暴力做法就是枚举si,再枚举sj然后去 t i + j t_{i+j} ti+j判断合法。首先判断两个字符串是否相等可以降低到O(1),就是用字符串哈希。然后分析时间复杂度 O ( n 2 ) O(n^2) O(n2)。肯定超时。
换一种思路:实际上我们枚举si时,只需要找到s串和从 t i + 1 t_{i+1} ti+1开始的最长公共前缀就能贡献答案(贡献答案就是si后面的长度)那么我们可以通过二分来寻找最大公共前缀。二分s的长度然后通过哈希与 t i + 1 t_{i+1} ti+1~ t i + 1 + m i d t_{i+1+mid} ti+1+mid之间字符串判断即可。
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9+7;
string s,t;
int p=233;//10不行
ll hasha[N],hashb[N];
void hash_(string str,ll a[])
{
a[0]=str[0]-'a';
int n=str.size();
for(int i=1;i<n;i++){
a[i]=(a[i-1]*p+str[i]-'a')%mod;
}
}
ll q_pow(ll a,ll b)
{
ll res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll calhash(ll a[],int l,int r)
{
if(l==0)return a[r];
else return ((a[r]-a[l-1]*q_pow(p,r-l+1)%mod)%mod+mod)%mod;
}
int main() {
cin>>s>>t;
hash_(s,hasha);
hash_(t,hashb);
ll res=0;
int lens=s.size(),lent=t.size();
for(int i=0;i<lens;i++){
// if(s[i]!=t[i])break;
if(hasha[i]!=hashb[i])break;
int l=0,r=lens-1,temp=-1;
while(l<=r){
int mid=l+r >>1;
ll ls=hasha[mid],lt;
if(i+1+mid>=lent)lt=-1;
else lt=calhash(hashb,i+1,i+1+mid);
if(ls==lt){
temp=mid;l=mid+1;
}else r=mid-1;
}
if(temp!=-1)res+=temp+1;
}
cout<<res<<'\n';
return 0;
}
J邬澄瑶的公约数
这道题就是求一些数的gcd。首先线筛把质数筛出来,然后对其分解质因数。实际上这里的 x i , p i x_i,p_i xi,pi需要分解成 ( 2 a 1 ∗ 3 a 2 ∗ . . . ∗ p n a n ) p i (2^{a1}*3^{a2}*...*pn^{an})^{p^i} (2a1∗3a2∗...∗pnan)pi。分解里面的最后cot*pi求最小即可。这里的vis2是为了保证求所有数都出现质数,然后才能放到答案里
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e4+5;
ll mod=1e9+7;
int X[N],Y[N],prime[N],vis[N],vis2[N];
void solve()
{
int t;
cin>>t;
while(t--){
}
}
ll q_pow(ll a,ll b)
{
ll res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
void get_prime(int n)
{
for(int i=2;i<=n;i++){
if(!vis[i])prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
int main() {
//solve();
int n,maxx=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>X[i];
}
for(int i=0;i<n;i++)cin>>Y[i];
map<int,int>mp;
get_prime(10005);
for(int i=0;i<n;i++){
int x=X[i],p=Y[i];
if(!vis[x]){
if(mp.find(x)==mp.end()){
mp[x]=p;vis2[x]++;
}else {
mp[x]=min(mp[x],p);vis2[x]++;
}
continue;
}
for(int j=1;j<=prime[0];j++){
int cot=0;
if(x%prime[j]==0){
while(x%prime[j]==0){
cot++;x/=prime[j];
}
if(mp.find(prime[j])==mp.end()){
mp[prime[j]]=cot*p;vis2[prime[j]]++;
}else {
mp[prime[j]]=min(mp[prime[j]],cot*p);vis2[prime[j]]++;
}
}
}
if(x>1){
mp[x]=1;vis2[x]++;
}
}
ll res=1;
for(auto it:mp){
ll x=it.first,p=it.second;
// cout<<x<<' '<<p<<' '<<vis2[x]<<'\n';
if(vis2[x]==n)
res=res*q_pow(x,p)%mod;
}
cout<<res<<'\n';
//cout<<gcd(4,6);
return 0;
}
/*
3
9 3 6
1 2 3
27
5
1236 218 124 326 182
2231 823 215 214 325
908002374
2
2 4
2 2
*/
H吴楚月的表达式
求一棵树上的表达式。
因为涉及到±*/必然有优先级的考虑。求的是每个节点的表达式。所以我们在遍历树的时候不能只算该节点的结果。还需要考虑后面的影响。比如2+3*5。第一个节点2,第二个节点res=2+3=5。但是第三个节点不能从第二个节点推出来了。res=5*5,这个是错的。所以必须考虑乘除的优先级。对每个节点不妨设他的计算形式a+b形式的(其中b是为了后边便于乘所需要的维护的)。这样我们每次维护这种就可以考虑到优先级。比如样例。对于1节点的权值3。维护该节点{a=0,b=3}。
如果下一个节点是+,那么{a2=a1+b1,b2=node[2]}(node[i]是第i个节点的权值)
如果下一个节点是-,那么{a2=a1+b1,b2=(-node[2]+mod)%mod}(该题对res%mod,这里防止负数)
如果下一个节点是* ,那么{a2=a1,b2=b1*node[2]}
如果下一个节点是/,那么{a2=a1,b2=b1*q_pow(node[2],mod-2)}(除法需要用到逆元)
综上:对于每个节点res=resa[i]+resb[i]即可。就是a+b的形式
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9+7;
int node[N],fa[N];
ll resa[N],resb[N];
vector<pair<int,char>>e[N];
string op;
void solve()
{
int t;
cin>>t;
while(t--){
}
}
ll q_pow(ll a,ll b)
{
ll res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void fun(int u,int fa,char opp)
{
if(opp=='+'){
resa[u]=(resa[fa]+resb[fa])%mod;
resb[u]=node[u]%mod;
}else if(opp=='-'){
resa[u]=(resa[fa]+resb[fa])%mod;
resb[u]=(-node[u]%mod+mod)%mod;
}else if(opp=='*'){
resa[u]=resa[fa];
resb[u]=resb[fa]*node[u]%mod;
}else if(opp=='/'){
resa[u]=resa[fa];
resb[u]=(resb[fa]*q_pow(node[u],mod-2)%mod)%mod;
}
}
void dfs(int u,int fa,char opp)
{
if(u!=1){
fun(u,fa,opp);
}
for(unsigned int i=0;i<e[u].size();i++){
int v=e[u][i].first;
char opp=e[u][i].second;
if(v==fa)continue;
dfs(v,u,opp);
}
return ;
}
int main() {
// solve();
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>node[i];
for(int i=1;i<=n-1;i++)cin>>fa[i];
cin>>op;
for(int i=1;i<=n-1;i++){
int u=fa[i],v=i+1;
char opp=op[i-1];
// e[v].push_back(u);
e[u].push_back({v,opp});
}
resa[1]=0,resb[1]=node[1];
dfs(1,-1,'-');
for(int i=1;i<=n;i++){
if(i>1)cout<<' ';
cout<<(resa[i]+resb[i])%mod;
}
cout<<'\n';
return 0;
}
/*
6
3 4 2 2 3 5
1 1 3 4 5
/*-**
3 750000006 6 4 0 999999983
*/