A:题目要每对直接的距离相同,那么把每对相邻,那么每对距离一定相同,所以直接对题目给的字符串进行排序输出即可,,排序、构造
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false) ;
int n ;
cin >> n ;
while (n--){
string x ;
cin >> x ;
sort(x.begin(),x.end()) ; // 排序输出
cout << x << "\n" ;
}
return 0;
}
B:按照题目中的模拟, 模拟
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
int main(){
ios::sync_with_stdio(false) ;
cin.tie(0) ;
cout.tie(0) ;
int t ;
cin >> t ;
while(t --){
string x ;
cin >> x;
int mx = 0; // mx指将mx和mx+1下标合并,可以得到最大值,先设置为0
for(int i = 1; i + 1 < x.size() ; i ++){
int a = x[mx] - '0' + x[mx + 1] - '0' ;
int b = x[i] - '0' + x[i+1] - '0' ;
if(a >= 10 && b < 10 || (a < 10 && b < 10)) ; // 当这两个种情况不需要更新最大值
else mx = i ;
}
string ans ;
for(int i = 0 ; i < x.size() ; i++){
if(i == mx){
int a = x[mx] - '0' + x[mx + 1] - '0' ;
if(a >= 10){
ans.push_back('1') ;
a %= 10 ;
}
ans.push_back(a + '0') ;
i ++ ;
}jik1
else ans.push_back(x[i]) ;
}
int k = 0 ; // 输出最大值即可
while(k + 1 < ans.size() && ans[k] == '0') k ++ ;
for(int i = k ; i < ans.size() ; i ++) cout << ans[i] ;
cout << '\n' ;
}
return 0;
}
贪心
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 110 ;
int n ;
ll k[N],h[N] ;
int main(){
int t ;
scanf("%d",&t) ;
while(t--){
scanf("%d",&n) ;
for(int i = 1; i <= n ; i ++) scanf("%lld",&k[i]) ;
for(int i = 1; i <= n ; i ++) scanf("%lld",&h[i]) ;
ll pre = 0,mx = -1;
ll ans = 0 ;
for(int i = n ; i >= 1 ; i--){ // 从后往前循环
ll t = max(pre,h[i]) ; // 这时候的高度应该取当前需要的高度和上一个需要高度的最大值
mx = max(mx,k[i]) ; //代表这一段的最右端点
if(k[i] - k[i-1] >= t){ // 如果这段距离满足t的高度,那么对i-1没有限制了
ll w = mx - k[i] + t ; // 那么这个是施法的长度,就是最右端点减去当前端点加上t
ans += w * ( w + 1) / 2 ; // 记录答案
mx = -1 ; // 初始化
pre = 0 ;
}
else pre = t - (k[i] - k[i-1]) ; // 记录i-1应该达到的最小高度 ,, 贪心
}
printf("%lld\n",ans) ;
}
return 0;
}
枚举,二分
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
const int N = 2e5 + 100 ;
int n,m ;
int a[N] ;
int cnt[N] ;
vector<int> nums ;
int er[N] ;
void init(){
for(int i = 0 ;i <= 18 ; i ++ ) er[i] = 1 << i ;
}
int get(int x){
return lower_bound(nums.begin(),nums.end(),x) - nums.begin() ;
}
int main(){
init() ;
int t;
scanf("%d",&t) ;
while(t--){
scanf("%d",&n) ;
nums.clear() ;
for(int i = 1 ; i <= n ; i++) scanf("%d",&a[i]) ,nums.push_back(a[i]) ;
sort(nums.begin(),nums.end()) ; // 离散化
nums.erase(unique(nums.begin(),nums.end()),nums.end()) ;
for(int i = 1; i <= n ; i ++) cnt[get(a[i])] ++ ;
m = nums.size() ;
int ans = 1e9 ;
for(int i = 0 ; i <= 18 ; i ++){ // 枚举第一段
for(int j = 0 ; j <= 18 ; j ++){ // 枚举第二段
int res = 0 ,tot = 0,z = n ;
int k = 0;
while(k < m && tot + cnt[k] <= er[i]) tot += cnt[k ++] ;
res += er[i] - tot ;
z -= tot ;
tot = 0 ;
while(k < m && tot + cnt[k] <= er[j]) tot += cnt[k ++] ;
res += er[j] - tot ;
z -= tot ;
res += er[lower_bound(er,er+19,z) - er] - z ; // 二分第三段
ans = min(ans,res) ;
}
}
for(int i = 0 ; i < m ; i++) cnt[i] = 0 ;
printf("%d\n",ans) ;
}
return 0;
}
参考 小岛美奈子
图的遍历,发现性质如何才能移动
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 3e6 + 100 , M = 2* N ;
int n,m,sum ;
int h[N],e[M],w[M],ne[M],idx ; // w为1代表新图中这条路可以走
int cnt[N] ;
bool col[N],st[N] ;
void add(int a,int b){
e[idx] = b,ne[idx] = h[a],h[a] = idx ++ ;
}
void dfs1(int u,int fa){
if(col[u]) cnt[u] = 1;
for(int i = h[u] ; ~ i ; i = ne[i]){
int j = e[i] ;
if(j == fa) continue ;
dfs1(j,u) ;
cnt[u] += cnt[j] ;
if(cnt[j] >= 2 ) w[i^1] = 1; //这里是可以下去找黑点,那么反过来,就是可以从下面上来
if(sum - cnt[j] >= 2) w[i] = 1; // 同理
if(col[j] || col[u]) w[i] = w[i^1] = 1 ; // 黑点周围的
}
}
void dfs2(int u){
st[u] = 1,col[u] = 1;
for(int i = h[u] ; ~ i ; i = ne[i]){
int j = e[i] ;
if(!st[j] && w[i]){
dfs2(j) ;
}
}
}
int main(){
ios::sync_with_stdio(false) ;
cin.tie(0) ;
cout.tie(0) ;
cin >> n ;
m = n - 1 ;
memset(h,-1,sizeof h) ;
for(int i = 1; i <= n ; i ++) cin >> col[i] ;
for(int i = 1; i <= n ; i++) if(col[i]) sum ++ ;
for(int i = 0 ; i < m ; i ++){
int a,b;
cin >> a >> b;
add(a,b),add(b,a) ;
}
dfs1(1,-1) ;
for(int i = 1 ; i <= n ; i++)
if(col[i] && !st[i])
dfs2(i) ;
for(int i = 1; i <= n ; i ++) cout << col[i] << " " ;
cout << '\n' ;
return 0;
}
F题
参考rainboy
dp,排列组合
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll ;
const ll N = 1e7 + 100 ,mod = 998244353 ;
const ll L = 720720 ;
ll n,x,y,k,M ;
ll aa[N] ;
ll f[N] ;
int main(){
cin >> n >> aa[0] >> x >> y >> k >> M ;
for(int i = 1 ; i < n ; i++) aa[i] = (aa[i-1] * x + y) % M ;
ll p = 1 ;
for(int i = k ; i >= 1; i --){
for(int j = L; j >= 0 ; j --) f[j] = (f[j] * (n - 1) % mod + j * p % mod + f[j - j % i]) % mod ; // 这是从后面操作像前面递推
if(i > 1) p = p * n % mod ;
}
ll ans = 0 ;
for(int i = 0 ; i < n ; i ++){
ans = (ans + k * p % mod * (aa[i] - aa[i] % L) % mod + f[aa[i] % L]) % mod ; // 这里k代表k个位置每个位置贡献,所以k * n^(k-1)就是i这个数的所有固定贡献,再加上i这个数的模数贡献
}
cout << ans << "\n" ;
return 0 ;
}