“强智杯“2020年湖南省大学生计算机程序设计竞赛(重现赛)B D H

B:2020 vs 2018

题目链接:2020vs2018
思路:由于各个数字之间的字符是由间隔的,因此只需要找出有特点的字符即可,我这边找的是数字1
代码:

#include
using namespace std;
#include
#include
#include
typedef long long ll;
const long long int maxn = 100;
int n, m;
char a[maxn][maxn];
int solve(int x, int y) {//在中间
    for (int i = x + 1; i <= n; i++) {
        if (a[i][y] != 'o') {
            break;
        }
        if ((a[i][y - 1] != '.') || (a[i][y + 1] != '.')) {
            return 0;
        }
 
    }
    //cout << x << " " << y << endl;
    return 1;
}
int solve1(int x) {//在左边
    for (int i = x+1; i <= n; i++) {
        if (a[i][1] != 'o') {
            break;
        }
        if (a[i][2] != '.') {
            return 0;
        }
    }
    return 1;
}
int solve2(int x) {//在右边
    for (int i = x + 1; i <= n; i++) {
        if (a[i][m] != 'o') {
            break;
        }
        if (a[i][m - 1] != '.') {
            return 0;
        }
    }
    return 1;
}
int main() {
    while (cin >> n >> m) {
        getchar();
        int flag = 0;
        int f = 0;
        for (int i = 1; i <= n; i++) {
            cin.getline(a[i] + 1, 100, '\n');
        }
        for (int i = 1; i <= n; i++) {
            for (int j= 1; j<= m; j++) {
                if (a[i][j] == 'o'&&j!=1&&j!=m&&(a[i][j+1]=='.'&&a[i][j-1]=='.')&&solve(i,j)) {
                    flag = 1;
                    //cout << i << " " << j << endl;
                    break;
                }
                if (j == 1 && a[i][j] == 'o' && (j + 1) <= m&&a[i][j+1]=='.'&&solve1(i)) {
                        flag=1;
                        //cout << i <<" "<< j << endl;
                        break;
                }
                if (j == m && a[i][j] == 'o' && (j - 1) >= 1&&a[i][j-1]=='.'&& solve2(i)) {
                    flag = 1;
                    //cout << i << " " << j << endl;
                    break;
                }
 
            }
            if (flag) {
                break;
            }
        }
        if (flag) {
            cout << "2018" << endl;
        }
        else {
            cout << "2020" << endl;
        }
    }
    return 0;
}

D:String Commutativity

题目链接:String Commutativity
思路:由于是找前后连接起来相同的字符串对数,所以就需要sj字符串和si的前缀和后缀相同,即为循环节的定义,用最小循环表示各个字符串即可
代码:

#include
using namespace std;
typedef long long int ll;
const ll maxn=1e6+100;
const ll N=1e6+100;
const int inf32=0x3f3f3f3f;
const ll inf64=0x3f3f3f3f3f3f3f3f;
const double eps=1e-8;
map<string,ll> p;
string s;
string s1;
ll n,m;
ll nex[maxn];
void getnex(){//kmp找next数组
    int j=-1;
    nex[0]=-1;
    int i=0;
    int len=s.length();
    while(i<len){
        if(j==-1||s[i]==s[j]){
            i++;
            j++;
            nex[i]=j;
        }else{
            j=nex[j];
        }
    }
}
int main(){
    while(~scanf("%d",&m)){
        ll ans=0;
        for(int i=1;i<=m;i++){
            cin>>s;
            n=s.length();
            getnex();
            ll k=0;
            if(n%(n-nex[n]))k=1;
            else{
                k=n/(n-nex[n]);
            }
            s1=s.substr(0,n/k);//获取最小循环节
            ans+=p[s1];
            p[s1]++;//数量加1
        }
        cout<<ans<<endl;
        p.clear();
    }
    return 0;
}

H:矩形并

题目链接:矩形并
思路:首先需要知道Area(i,j)全部相加的面积和,公式是

S=(n*(n+1)/2)(m(m+1)/2)

然后减去重复的即可,详情看代码
代码:

#include
using namespace std;
typedef long long int ll;
const ll maxn=1e6+100;
const ll N=1e6+100;
const int inf32=0x3f3f3f3f;
const ll inf64=0x3f3f3f3f3f3f3f3f;
const double eps=1e-8;
const ll mod=1e9+7;
ll a,b,x1,x2,Y1,y2;
/*ll call(ll xx,ll yy){
    ll tx=xx*((xx+1)%mod)%mod/(1ll * 2)%mod;
    ll ty=yy*((yy+1)%mod)%mod/(1ll * 2)%mod;
    return (tx*ty)%mod;
}*/
ll cal(ll xx, ll yy)
{
    return xx * (xx + 1) / (1ll * 2) % mod * (yy * (yy + 1) / (1ll * 2) % mod) % mod;
}//计算矩形面积累加
int main(){
    while(cin>>a>>b){
        cin>>x1>>x2>>Y1>>y2;
        ll ans=0;
        ans=(cal(a,b)%mod+ans)%mod;//加自身Area
        ans=(ans+a*b%mod*abs(Y1-y2)%mod*abs(x1-x2)%mod)%mod;//加上a*b个A
        if(x1<a&&Y1<b){
            ll ax=(a-x1),ay=(b-Y1);
            ans=(ans+mod-cal(ax,ay))%mod;//减去重复的
            if(x2<a){//加上右下面多剪得
                ll a2=a-x2;
                ans=(ans+cal(a2,ay))%mod;
            }
            if(y2<b){//加上坐上面多减的
                ll b2=b-y2;
                ans=(ans+cal(ax,b2))%mod;
                if(x2<a){//减去前面多加上的
                    ll a3=a-x2,b3=b-y2;
                    ans=(ans-cal(a3,b3)+mod)%mod;
                }
            }
        }
        printf("%lld\n",ans);

    }
	return 0;
}

你可能感兴趣的:(数据结构,字符串)