子串分值
错误理由:哈哈哈,错得很尴尬。先用暴力写了一发,后来发现可以用字母的位置来写,复杂度会小一点,但是推导样例的时候没有想到乘法的情况。哈哈哈哈哈,***。
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+100;
const int M=3000;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;
string str;
priority_queue<ll,vector<ll>,greater<ll>> q[30];
set<ll> save;
signed main (void)
{
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>str;
ll len=str.size();
str=" "+str;
ll ans=0;
for(int i=1;i<=len;i++)
{
save.insert(str[i]-'a');
q[str[i]-'a'].push(i);
}
for(auto T_T:save)
{
ans+=q[T_T].size();
ll first=q[T_T].top();
q[T_T].pop();
ans+=first-1;
ll last_add=first-1;
while(q[T_T].size())
{
ll next=q[T_T].top();
q[T_T].pop();
ans+=(next-first-1)*2;
ans+=last_add*(next-first-1);
last_add=next-first-1;
// cout<<last_add<<" ha "<<endl;
first=next;
}
// cout<<last_add<<" ha "<<endl;
ans+=(len-first)*last_add;
ans+=len-first;
// cout<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}
整数拼接
错误理由:哈哈哈,错得更尴尬了。最开始直接把a[i]取模了,最后前面数字乘上十的倍数那里就算错了。***。
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e5+100;
const int M=3000;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;
ll n,m;
ll a[N];
map<ll,map<ll,ll>> q;
// 将每一个数字作为右边瞧一瞧 看看有没有余数相同的
ll ans;
ll ten[15];
signed main (void)
{
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>n>>m;
ten[0]=1;
for(int i=1;i<=10;i++)
ten[i]=(ten[i-1]*10)%m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
for(int j=1;j<=10;j++)
{
q[j][(a[i]*ten[j])%m]++;
}
}
for(int i=1;i<=n;i++)
{
ll len= to_string(a[i]).size();
ans+=q[len][(m-(a[i]%m))%m];
if(((a[i]%m)*ten[len])%m==(m-(a[i])%m)%m)
ans--;
}
cout<<ans<<endl;
return 0;
}
画中漂流
错误理由:首先最开始题意理解没错,一秒钟就是可以消耗一点体力或者不消耗,那么要想最后体力不剩余,m<=t,但是题目并没有保证,我慌了。于是开始编造每一秒钟可以消耗不止一点体力。猜测是dp,但是没有想出来,就dfs写了一发… 哈哈哈,愚蠢的人类
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int P=131;
const int N=3100;
const int MOD=1e9+7;
// 每秒只能够消耗一点体力 或者不消耗体力....
// 又读错题意了
// 当时是想不通 那么既然一秒只能够消耗一点体力 那么体力值m一定是小于等于t才是有解的咯
ll d,t,m;
ll f[N][N];
// 在第i秒使用j点体力的方案数是多少
signed main (void)
{
cin>>d>>t>>m;
f[0][0]=1;
for(int i=1;i<=t;i++)
{
for(int j=min(i,m);j>=0;j--)
{
// i-j是不使用体力掉下去的情况
// j是上升的情况
// 如果掉下去的减去上升的大于等于的话 那么就是掉下悬崖了
if((i-j)-j>=d)
break;// 那么此时此刻的方案数就是为零的
// 如果能使用体力的话
if(j)
f[i][j]+=f[i-1][j-1];
// 如果能够往下掉的话
if((i-1-j)-j<d-1)
f[i][j]+=f[i-1][j];
f[i][j]%=MOD;
}
}
cout<<f[t][m]<<endl;
return 0;
}
最优包含
错误理由:数组开打了,MLE… 耻辱。虽然初始化的时候也错了,只初始化了f[0][0]的情况… 哈哈哈
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+100;
const int M=3000;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;
const int MOD=1000000007;
string str1,str2;
ll f[N][N];// 现在在第i个字符 已经有j个字符相等 需要的最小操作是多少
signed main (void)
{
// ios::sync_with_stdio(false);
// cin.tie(0);
memset(f,0x3f,sizeof f);
cin>>str1>>str2;
ll len1=str1.size();
ll len2=str2.size();
str1=" "+str1,str2=" "+str2;
for(int i=0;i<=len1;i++)
f[i][0]=0;
for(int i=1;i<=len1;i++)
{
for(int j=i;j>=1;j--)
{
f[i][j]=f[i-1][j];
if(str1[i]==str2[j])
f[i][j]=min(f[i][j],f[i-1][j-1]);
else
f[i][j]=min(f[i][j],f[i-1][j-1]+1);
}
}
cout<<f[len1][len2]<<endl;
return 0;
}
网络分析
错误理由:不是很懂优化的方法,就纯暴力写了。赛后听说是启发式合并,"装模做样"地写了一发,竟然过了,哈哈哈哈,还是得多学点算法。
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e4+100;
//#define int long long
typedef int ll;
typedef pair<ll,ll> PLL;
const int MOD=1000000007;
ll n,m;
vector<ll> save[N];
ll ans[N];
ll f[N];
ll find(ll x)
{
if(x==f[x])
return x;
return f[x]=find(f[x]);
}
signed main (void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
f[i]=i,save[i].push_back(i);
for(int i=1;i<=m;i++)
{
ll x,y,z; cin>>x>>y>>z;
if(x==1) {
if(find(y)== find(z))
continue;
if(save[find(y)].size()<save[find(z)].size())
{
for(auto T_T:save[find(z)])
save[find(y)].push_back(T_T);
f[find(z)]= find(y);
}
else
{
for(auto T_T:save[find(y)])
save[find(z)].push_back(T_T);
f[find(y)]= find(z);
}
}
else {
for(auto T_T:save[find(y)])
ans[T_T]+=z;
// cout<<endl;
}
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
return 0;
}
限高杆
错误的理由:题意理解错了,以为只是恢复一条边,结果“两段道路”,哈哈哈哈。暴力写了一发。正解是分层图最短路,去好好学一学。
#include <iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e5+100;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;
struct Point{
ll x,y,z;
};
ll n,m;
vector<PLL> Edge[N];
vector<Point> q;
ll dist[N];
bool Vis[N];
void dijkstra(){
memset(dist,0x3f,sizeof dist);
memset(Vis, false,sizeof Vis);
dist[0]=0;
dist[0+n]=0;
dist[0+2*n]=0;
priority_queue<PLL,vector<PLL>,greater<PLL>> q;
q.push({0,0});
q.push({0,0+n});
q.push({0,0+n*2});
while(q.size())
{
PLL T_T=q.top();
q.pop();
if(Vis[T_T.second])
continue;
Vis[T_T.second]=true;
for(PLL j:Edge[T_T.second])
{
if(Vis[j.first])
continue;
if(dist[j.first]>T_T.first+j.second)
dist[j.first]=T_T.first+j.second,q.push({dist[j.first],j.first});
}
}
}
signed main (void)
{
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
ll x,y,z; cin>>x>>y>>z;
x--,y--;
ll k; cin>>k;
// 建一个两层的图
if(k==1){
Edge[y].push_back({x+n,z});
Edge[y+n].push_back({x+n*2,z});
Edge[x].push_back({y+n,z});
Edge[x+n].push_back({y+n*2,z});
}
else{
Edge[y].push_back({x,z}), Edge[x].push_back({y,z});
Edge[y+n].push_back({x+n ,z}), Edge[x+n].push_back({y+n,z});
Edge[y+2*n].push_back({x+n*2,z}), Edge[x+2*n].push_back({y+2*n,z});
}
}
dijkstra();
cout<<dist[n-1]-dist[n-1+2*n]<<endl;
return 0;
}
#include <iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=5e5+100;
#define int long long
typedef long long ll;
typedef pair<ll,ll> PLL;
ll n,m,k;
ll st,ed;
vector<PLL> Edge[N];
ll dist[N];
bool Vis[N];
ll ans=1e18;
void dijkstra(){
memset(dist,0x3f,sizeof dist);
memset(Vis, false,sizeof Vis);
priority_queue<PLL,vector<PLL>,greater<PLL>> q;
for(int i=0;i<=k;i++)
{
dist[st+i*n]=0;
q.push({0,st+i*n});
}
while(q.size())
{
PLL T_T=q.top();
q.pop();
if(Vis[T_T.second])
continue;
Vis[T_T.second]=true;
for(PLL j:Edge[T_T.second])
{
if(Vis[j.first])
continue;
if(dist[j.first]>T_T.first+j.second)
dist[j.first]=T_T.first+j.second,q.push({dist[j.first],j.first});
}
}
for(int i=0;i<=k;i++)
ans=min(ans,dist[ed+i*n]);
}
signed main (void)
{
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>n>>m>>k;
cin>>st>>ed;
for(int i=1;i<=m;i++)
{
ll x,y,z; cin>>x>>y>>z;
// 建一个k层的图
for(int j=0;j<=k;j++)
{
// 同一层 还有向下传递的
Edge[y+n*j].push_back({x+n*j,z});
Edge[x+n*j].push_back({y+n*j,z});
if(j){
// cout<<"ahah\n";
Edge[y+n*(j-1)].push_back({x+n*j,0});
Edge[x+n*(j-1)].push_back({y+n*j,0});
}
}
}
dijkstra();
cout<<ans<<endl;
return 0;
}
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 510000,INF = 0x3f3f3f3f;
typedef pair<int,int> PII;
int e[N],ne[N],w[N],h[N],idx;
int n,m,s,t,dis[N];
bool vis[N];
priority_queue<PII,vector<PII>,greater<PII> > q;
void add(int a,int b,int c)
{
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx++;
}
void dijkstra(int s)
{
memset(dis,INF,sizeof dis);
dis[s] = 0;
q.push({0,s});
while(!q.empty())
{
int u = q.top().second;
q.pop();
if(vis[u])
continue;
vis[u] = 1;
for(int i = h[u]; ~i;i = ne[i])
{
int v = e[i];
if(dis[v] > dis[u]+w[i])
{
dis[v] = dis[u]+w[i];
q.push({dis[v],v});
}
}
}
}
int main()
{
int price,ad,num,pre,cur;
cin >> n >> m >> s >> t;
memset(h,-1,sizeof h);
for(int i = 1;i <= m;i++)
{
cin >> price >> ad >> num;
for(int j = 0;j < num;j++)
{
cin >> cur;
if(j)
{
add((i-1)*n+pre,(i-1)*n+cur,ad);
add((i-1)*n+cur,(i-1)*n+pre,ad);
}
add((i-1)*n+cur,n*m+cur,0);
add(n*m+cur,(i-1)*n+cur,price);
pre = cur;
}
}
dijkstra(n*m+s);
if(dis[n*m+t] == INF)
cout << -1 << endl;
else
cout << dis[n*m+t] << endl;
return 0;
}
待补的题
皮亚诺曲线距离
没写的理由:这图也…太抽象了吧