YunYan

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

两种方法,递归和递推

记忆化搜索跑一边就行了

#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\n",s);
    printf("Node %d is the root node of the tree\n",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 待补

保存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\n",a[n]);
        printf("A->C:%lld\n",b[n]);
        printf("B->A:%lld\n",c[n]);
        printf("B->C:%lld\n",a[n]);
        printf("C->A:%lld\n",a[n]-n/(ll)2);
        printf("C->B:%lld\n",c[n]);
        printf("SUM:%lld\n",sum);
    return 0;
}

J待补

posted on 2020-02-09 21:26  Target--fly  阅读(151)  评论(0编辑  收藏  举报