A
签到
B. 在哈尔滨的寒风中
题意
给一个n×m的棋盘,问有多少对点可以互相到达(可以经过若干步)(n,m<=1e9)
分析
很显然,当棋盘很大时,所有点对都可以互相到达(比如:象棋棋盘),模拟可得:这个边界为3*4(大于等于3*4所有点都可到达),其他情况手动暴力模拟即可
还有另一种思路:找不到边界是我们可以假设边界为100*100(因为数据很大,不能直接暴力dfs),剩下暴力dfs找属于同一联通块的即可
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5+5 ; const int maxm = 1e5 + 3; const ll mod = 1e9+7; ll n,m; int main() { scanf("%lld%lld", &n ,&m); if(n>m) swap(n,m); if(n>=3&&m>=4) { ll ans=n*m; printf("%lld ", (ans*(ans-1))/2); } else if(n==3&&m==3) printf("28 "); else if(n==2) { ll ans1=((m+1)/2); ll ans2= (m-(m+1)/2); cout<<(ans1*(ans1-1))+(ans2*(ans2-1))<<endl; } else cout<<0<<endl; return 0; }
*C. 易位构词
题意
给一个单词s (1≤|s|≤105),问你是否存在一种改变字符的顺序使得每个字符都不在原来的位置上,存在输出单词,否则输出"impossible"
分析
直接将单词排序,循环向右移动最大连续相同的字符个数即可(具体实现还是有点困难的,学习!!!
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; const int maxm=1e5+5; int cnt[maxn]; char str[maxn]; char ans[maxn]; struct node { char s;int id; friend bool operator < (node x, node y) { if(cnt[x.s]!=cnt[y.s]) return cnt[x.s]>cnt[y.s] ; return x.s<y.s; } }a[maxn]; int main() { scanf("%s", str); int n=strlen(str); for(int i=0;i<n;i++) a[i]={str[i],i}, cnt[str[i]]++; sort(a,a+n); int mx=0; char ss=a[0].s; int i; for(i=0;i<n;i++) if(a[i].s!=ss) break; mx=i; if((mx<<1)>n) printf("impossible "); else { for(int i=0;i<n;i++) str[(i+mx)%n]=a[i].s; for(int i=0;i<n;i++) ans[a[i].id]=str[i]; ans[n]='