CF355div2

链接:http://codeforces.com/contest/677

c:Vanya and Label

题意:给你一个字符串s,每个字符可以用一个10进制数表示(0~63),现在要求有多少对与s长度一样的字符串通过&得到s。

分析:只用64个数,直接暴力出每两个数的&,然后相乘就行了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 50010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
ll get(char p) {
    int x=0;
    if(p>='0'&&p<='9') x=p-'0';
    else if(p>='a'&&p<='z') x=p-'a'+36;
    else if(p>='A'&&p<='Z') x=p-'A'+10;
    else if(p=='-') x=62;
    else if(p=='_') x=63;
    return x;
}
int a[70];
int main() {
    for(int i=0;i<64;i++) {
        for(int j=0;j<64;j++) {
            a[i&j]++;
        }
    }
    string s;
    cin>>s;
    ll sum=1;
    for(int i=0;i<s.size();i++) {
        sum=(sum*a[get(s[i])])%mod;
        //cout<<sum<<endl;
    }
    cout<<sum<<endl;
    return 0;
}
D:Vanya and Treasure
题意:给你一个n*m的矩阵,其中的数由1~p组成,现在要你找到一个1,2,.....p的顺序的最短曼哈顿距离。

分析:我们可以将所有相同值得分成一个点集,然后由i的所有点更新到i+1的所有点,更新过程如下:

将i的所有点的横轴标记为i,并且计算出他们最小距离,然后到i+1中所有点的距离就是由纵轴上的i更新过来的。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 300*300+5
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
vector<int> a[Mn];
int ans[Mn];
int dis[Mn];
int vis[Mn];
int main() {
    int n,m,p,x;
    cin>>n>>m>>p;
    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            scanf("%d",&x);
            a[x].push_back(i*m+j);
        }
    }
    CLR(dis,0x3f);
    CLR(ans,0x3f);
    for(int i=0;i<m;i++) {
        dis[i]=i;
        vis[i]=0;
    }
    for(int i=1;i<=p;i++) {
        for(auto now:a[i]) {
            int a2=now/m,b2=now%m;
            for(int j=0;j<n;j++) {
                int pre=j*m+b2;
                if(vis[pre]==i-1) {
                    ans[now]=min(ans[now],dis[pre]+abs(j-a2));
                }
            }
        }
        for(auto now:a[i]) {
            int a2=now/m,b2=now%m;;
            for(int j=0;j<m;j++) {
                int ne=a2*m+j;
                if(vis[ne]!=i) {
                    vis[ne]=i;
                    dis[ne]=ans[now]+abs(b2-j);
                } else {
                    dis[ne]=min(dis[ne],ans[now]+abs(b2-j));
                }
            }
        }
    }
    cout<<ans[a[p][0]]<<endl;
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值