A.暴力统计即可
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m;
int a[N];
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++){
int cnt=0;
for(int j=1;j<=7;j++)
{
int x;cin>>x;
cnt+=x;
}
cout<<cnt<<" ";
}
}
B.也是暴力即可
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m;
int a[N];
string s[N];
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++)
{
string t=s[i]+s[j];
int l=0,r=t.size()-1;
bool f=true;
// cout<<t<<"\n";
while(l<=r){
if(t[l]==t[r])
{
l++,r--;
}
else{
f=false;break;
}
}
if(f){
cout<<"Yes\n";return 0;
}
}
}
cout<<"No\n";
}
C.没写毒瘤题
D
栈模拟
碰到)并且栈里面有(就直接丢弃字符串后面的字符串直到碰到第一个(才停止
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m;
int a[N];
//string s[N];
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>n;
string s;
cin>>s;
stack<char> st;
string res;
for(int i=0;i<s.size();i++)
{
if(s[i]!=')'&&s[i]!='(')
{
res.push_back(s[i]); continue;
}
if(st.empty()) st.push(s[i]),res.push_back(s[i]);
else{
if(st.size()&&st.top()=='('&&s[i]==')')
{
while(res.size()&&res.back()!='(') res.pop_back();
res.pop_back();
st.pop();
continue;
}
else st.push(s[i]),res.push_back(s[i]);
}
}
cout<<res;
}
E.DP
状态前i个人,每个人相邻整数不同,且第i个人和第一个人整数相同(1)/不相同(0)
把环变成链即可
解释一下状态转移
f[i][0]:由两个方向转移 可以由前面f[i-1][0]*(m-2)由于要和第一个数不同且和前面一个数不同
f[i-1][1]*(m-1)因为前面一个数和第一个数相同,所以能选m-1个数
f[i][1]:只能由f[i-1][0]只能选第一个数的编号
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef pair<int, int> PII;
int n,m;
int f[N][3];
//string s[N];
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>n>>m;
f[1][1]=m;
for(int i=1;i<n;i++){
f[i+1][0]=(f[i][0]*(m-2)+f[i][1]*(m-1))%mod;
f[i+1][1]=f[i][0]%mod;
}
cout<<f[n][0]%mod;
}
F.
首先把没感染过的点全部进行入队(可以看错建立了个虚拟源点进行了第一轮感染)
因为每天的x感染距离不同
所以我们用另一个堆去记录这天扩展的到的点,如果扩展不到就继续放入到第一个堆
第一个堆就是记录哪些点还没被感染,第二个堆才是用来扩展点的
如果没被感染就是权值小于x,那么距离变成当前点到没感染点的权值,因为这个求得是最短路,可以顺便更新到没感染点的最短路
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef pair<int, int> PII;
int n,m,k,d;
vector<PII> g[N];
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;cin>>x>>y>>z;
g[x].push_back({y,z});
g[y].push_back({x,z});
}
cin>>k;
vector<int> res(n+1,-1);
priority_queue<PII,vector<PII>,greater<PII>> q;
for(int i=1;i<=k;i++){
int x;cin>>x;
res[x]=0;
for(auto&e:g[x]){
if(res[e.first]==-1)
q.push({e.second,e.first});
}
}
cin>>d;
for(int i=1;i<=d;i++)
{
priority_queue<PII,vector<PII>,greater<PII>> q1;
int x;cin>>x;
while(q.size())
{
auto p=q.top();
if(p.first>x) break;
q.pop();
if(res[p.second]!=-1) continue;
q1.push(p);
}
while(q1.size())
{
auto p=q1.top();
q1.pop();
if(res[p.second]!=-1) continue;
auto y=p.second;
res[y]=i;
for(auto e:g[y]){
if(res[e.first]==-1)
{
if(p.first+e.second<=x){
q1.push({p.first+e.second,e.first});
}
else{
q.push({e.second,e.first});
}
}
}
}
}
for(int i=1;i<=n;i++) cout<<res[i]<<"\n";
}
G.
首先对于两个操作,不会改变总和,且要求相差最大为1
那么最多只能是两个不同的数
我们设x=sum/n,y=sum%n
=x=sum/n,y=x+1
因为sum不能整除多出来了只能相加1
所以dp可设置成
前i个数能用j个+1
转移有点麻烦
我们要记录前面数的总和,求到当前数的时候,因为我们已经知道前面已经用了(y-j)个加一
且前面数的总和是pre,有(y-j)个数是x+1,另外的(i-(y-j))个数是x
那么我们就能准确的算出当前数变成什么数了
如果还能用+1
f[i][j]=min(f[i][j],f[i-1][j]+abs(cur-x));就是不用+1,把当前数变成x需要的次数
f[i][j-1]=min(f[i][j-1],f[i-1][j]+abs(cur-(x+1)));就是把当前数变成x+1需要的次数,用来更新发f[i][j-1]
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
int INF=1e18;
typedef pair<int, int> PII;
int n,m;
int a[N];
int f[5010][5010];
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
cin>>n;
int s=0;
for(int i=1;i<=n;i++) cin>>a[i],s+=a[i];
int x=s/n,y=s%n;
if(y<0){
y=n+y;
x--;
}
memset(f,0x3f,sizeof(f));
f[0][y]=0;
int pre=0;
for(int i=1;i<=n;i++)
{
int z=a[i];
for(int j=0;j<=y;j++)//还有j个x+1能用
{
int cur=z-(x*(i-1)-pre + y-j);
f[i][j]=min(f[i][j],f[i-1][j]+abs(cur-x));
if(j)
f[i][j-1]=min(f[i][j-1],f[i-1][j]+abs(cur-(x+1)));
}
pre+=z;
}
cout<<f[n][0];
}