A
两种方法,递归和递推
记忆化搜索跑一边就行了
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const ll N=100; ll dp[N][N]; char arr[N][N]; ll n,m; bool flag=0; ll dfs(ll x,ll y) { if(dp[x][y]) return dp[x][y]%mod; if(arr[x][y]=='R'&&y+1<=m) dp[x][y]=(dp[x][y]+dfs(x,y+1))%mod; if(arr[x][y]=='D'&&x+1<=n) dp[x][y]=(dp[x][y]+dfs(x+1,y))%mod; if(arr[x][y]=='B') { if(x+1<=n) dp[x][y]=(dp[x][y]+dfs(x+1,y))%mod; if(y+1<=m)dp[x][y]=(dp[x][y]+dfs(x,y+1))%mod; } return dp[x][y]%mod; } int main() { cin>>n>>m; for(ll i=1;i<=n;i++) scanf("%s",arr[i]+1); dp[n][m]=1; ll x=dfs(1,1)%mod; cout<<x<<endl; return 0; }
递推,o(n^2),遍历每一个点,同时判断每一个点的上一个状态。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const ll N=70; char arr[N][N]; ll dp[N][N]; int main() { ll n,m; cin>>n>>m; for(ll i=1;i<=n;i++) scanf("%s",arr[i]+1); dp[1][1]=1; for(ll i=1;i<=n;i++){ for(ll j=1;j<=m;j++){ if(arr[i][j-1]=='R'||arr[i][j-1]=='B') dp[i][j]=(dp[i][j]+dp[i][j-1])%mod; if(arr[i-1][j]=='D'||arr[i-1][j]=='B') dp[i][j]=(dp[i][j]+dp[i-1][j])%mod; } } cout<<dp[n][m]%mod<<endl; return 0; }
B 待补
C,水,提交之前最好用自测功能试一下。。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=1E3+7; ll arr[N][N]; void solve(){ ll n,m,p; cin>>n>>m>>p; bool re=0; bool Be=0; for(int i=0;i<n;i++){ for(int j=0;j<m;j++) arr[i][j]=0; } while(p--){ ll x,y,v; cin>>x>>y>>v; if(re) continue ; if(x<0||y<0||x>=n||y>=m) Be=1; ll c=m*x+y; if(c>m*(n-1)+m-1||c<0) { re=1; } else { arr[c/m][c%m]=v; } } if(re) cout<<"Runtime error"<<endl; else if(Be){ for(ll i=0;i<n;i++){ for(ll j=0;j<m;j++){ cout<<arr[i][j]; if(j==m-1) break ; cout<<" "; } cout<<endl; } cout<<"Undefined Behaviour"<<endl; } else { for(ll i=0;i<n;i++){ for(ll j=0;j<m;j++){ cout<<arr[i][j]; if(j==m-1) break; cout<<" "; } cout<<endl; } cout<<"Accepted"<<endl; } } int main(){ int t; cin>>t; while(t--) solve(); return 0; }
D 水
#include<bits/stdc++.h> using namespace std; const int N=1E5+7; int arr[N]; int brr[N]; int main(){ int n; cin>>n; int s=0; for(int i=1;i<=n;i++){ cin>>arr[i]; if(arr[i]==-1) continue ; s++; brr[arr[i]]=i; } printf("The size of the tree is %d ",s); printf("Node %d is the root node of the tree ",arr[1]); bool father=0; for(int i=1;i<=s;i++){ int c=brr[i]; if(c/2==0){ printf("The father of node %d is -1, ",i); } else { printf("The father of node %d is %d, ",i,arr[c/2]); } if(2*c>n) printf("the left child is -1, "); else { printf("the left child is %d, ",arr[2*c]); } if(2*c+1>n) printf("and the right child is -1"); else { printf("and the right child is %d",arr[2*c+1]); } if(i==s) continue ; cout<<endl; } return 0; }
E 待补
F
保存1的位置,求前缀和,可以直接求,也可以套线段树。答案就是1前面的1的个数乘以当前1的位置数再减去当前1前面1的位置的前缀和,然后累加。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const ll N=1E5+7; ll arr[N]; ll dp[N]; int main() { ll n; cin>>n; string s; cin>>s; ll pos=0; for(ll i=0;i<n;i++) { if(s[i]=='1') arr[pos++]=i; } if(pos==1){ cout<<0<<endl; return 0; } dp[0]=arr[0]; for(ll i=1;i<pos;i++) dp[i]=arr[i]+dp[i-1]; ll sum=0; for(ll i=pos-1;i>=0;i--){ sum=(sum+i*arr[i])%mod; sum=(sum-dp[i-1]+mod)%mod; } cout<<(sum+mod)%mod<<endl; return 0; }
F
线段树,
假设初始状态 有4个1,其位置分别为a b c d e,此时答案为ans,在cd之间插入了一个e1那么新增加的对为e-e1+d-e1+e1-c+e1-b+e1-a。所以答案为e1后边的数的和减去e1*e1后边1的个数加上e1*e1左边1的个数再减去从1到c的和。所以我们可以用线段树的方法维护区间和。在这里我们维护两个线段树,第一个为位置前缀和,第二个为1的个数的前缀和。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=1E5+7; const ll mod=1E9+7; ll arr[N]; ll tree[N+N+N]; ll t1[N+N+N]; void buid_tree(ll node,ll start,ll end){//建树 if(start==end){ tree[node]=arr[end]; if(arr[end]!=0) t1[node]=1; else t1[node]=0; return ; } ll mid=(start+end)>>1; ll left_node =2*node; ll right_node =2*node+1; buid_tree(left_node ,start,mid); buid_tree(right_node,mid+1,end); tree[node]=(tree[left_node]+tree[right_node])%mod; t1[node]=t1[left_node]+t1[right_node]; } void update(ll node,ll start,ll end,ll idx,ll value){//节点更新 if(start==end) { arr[idx]=(arr[idx]+value+mod)%mod; tree[node]=(tree[node]+value+mod)%mod; if(arr[idx]==0) t1[node]--; else t1[node]++; return ; } ll mid=(start+end) / 2 ; ll left_node=2*node; ll right_node=2*node+1; if(idx>=start && idx<=mid) update(left_node,start,mid,idx,value); else update(right_node,mid+1,end,idx,value); tree[node]=(tree[left_node]+tree[right_node]+mod)%mod; t1[node]=t1[left_node]+t1[right_node]; } ll query_tree(ll node,ll start,ll end,ll l,ll r,bool x){//查询函数 if(l>end||r<start) return 0; else if(start==end||l<=start&&end<=r){ if(x==1) return (tree[node]+mod)%mod; else return t1[node]; } ll mid=(start+end)/2; ll left_node=2*node;//左儿子 ll right_node=2*node+1;//右儿子 ll sum_left=query_tree(left_node,start,mid,l,r,x); ll sum_right=query_tree(right_node,mid+1,end,l,r,x); return (sum_left+sum_right+mod)%mod; } int main(){ ios::sync_with_stdio(false); ll n; cin>>n; string s; cin>>s; for(ll i=0;i<n;i++){ if(s[i]=='1') arr[i+1]=i+1; else arr[i+1]=0; } buid_tree(1,1,n); ll ans=0; for(ll i=n;i>=1;i--){ if(arr[i]==0) continue ; ll sum_left=query_tree(1,1,n,1,i,1); ll sum_1 =query_tree(1,1,n,1,i,0); ans=(ans+sum_1*i-sum_left)%mod; } ans=(ans+mod)%mod; cout<<ans<<endl; ll m; cin>>m; while(m--){ ll x,y; cin>>x>>y; if(x==1){ update(1,1,n,y,y); ll sum_left=query_tree(1,1,n,1,y-1,1); ll sum_l1=query_tree(1,1,n,1,y-1,0); ll sum_right=query_tree(1,1,n,y+1,n,1); ll sum_r1=query_tree(1,1,n,y+1,n,0); ll x=(sum_l1*y-sum_left+sum_right-sum_r1*y+mod)%mod; ans=(ans+x+mod)%mod; } else { update(1,1,n,y,-y); ll sum_left=query_tree(1,1,n,1,y-1,1); ll sum_l1=query_tree(1,1,n,1,y-1,0); ll sum_right=query_tree(1,1,n,y+1,n,1); ll sum_r1=query_tree(1,1,n,y+1,n,0); ll x=(sum_l1*y-sum_left+sum_right-sum_r1*y+mod)%mod; ans=(ans-x+mod)%mod; } cout<<ans<<endl; } return 0; }
H题:
这个题目就。。。其实就一个素数打表,一开始就相到了,但是觉得会超时,就没敢往下想。最后没想到这么水,。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=2E5+7; bool prime[N]={1,0,0}; ll arr[N]; void inll(){ for(ll i=2;i*i<=N;i++) if(!prime[i])//素数是0 for(ll j=i+i;j<=N;j+=i) prime[j]=1;//素数的倍数一定不是素数 } ll su(ll x){ ll s=0; ll c=sqrt(x); for(ll i=1;i<=c;i++){ if(x%i==0){ ll a=x/i; if(prime[i]) s++; if(prime[a]&&a!=i) s++; } } return s; } int main(){ inll(); prime[1]=0; ll n,m; cin>>n>>m; for(ll i=1;i<=n;i++){ if(prime[i]){ arr[su(i)]++; } } for(ll i=1;i<=m;i++){ ll k; cin>>k; cout<<arr[k]<<endl; } return 0; }
I
规律题
打表找递推式就行。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=70; ll a[N],b[N],c[N],d[N],e[N],f[N]; ll ksm(ll a,ll b) { ll res=1; while(b){ if(b&1) res=res*a; a=a*a; b>>=1; } return res; } int main(){ a[1]=0;a[2]=1; b[1]=1;b[2]=1; c[1]=0;c[2]=0; for(ll i=3;i<=60;i++){ if(i&1) a[i]=a[i-1]; else a[i]=b[i-1]+c[i-1]; if(i&1) b[i]=a[i-1]*(ll)2+(ll)1; else b[i]=b[i-1]; if(i&1) c[i]=b[i]-(i+(ll)1)/(ll)2; else c[i]=c[i-1]; } ll n; cin>>n; ll sum=ksm(2,n)-(ll)1; printf("A->B:%lld ",a[n]); printf("A->C:%lld ",b[n]); printf("B->A:%lld ",c[n]); printf("B->C:%lld ",a[n]); printf("C->A:%lld ",a[n]-n/(ll)2); printf("C->B:%lld ",c[n]); printf("SUM:%lld ",sum); return 0; }
J待补