霸气de小男生 提交于 2020-01-17 19:26:39

------------恢复内容开始------------

///一道简单dp,题意:让你求出给出数列中加起来可以整出 m的方案数

///一道简单dp,题意:让你求出给出数列中加起来可以整出 m的方案数
///dp【i】【j】表示前i个中你挑选n个(1<=n<=i)余数为j的方案数
///所以转移方程为 dp[i - 1][j]未有i时的方案数加上 dp[i - 1][(j + f - a[i] % f) % f]即将加上i(所以得减去a【i】)这样+a[i]才有j
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int mod = 1e8;
const int maxn = 1e3 + 5;
inline ll read()
{
    ll ans = 0;
    char ch = getchar(), last = ' ';
    while(!isdigit(ch)) {last = ch; ch = getchar();}
    while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    if(last == '-') ans = -ans;
    return ans;
}
inline void write(ll x)
{
    if(x < 0) x = -x, putchar('-');
    if(x >= 10) write(x / 10);
    putchar(x % 10 + '0');
}

int n, f, a[maxn << 1];
int dp[maxn << 1][maxn];

int main()
{
    n = read(); f = read();
    for(int i = 1; i <= n; ++i) a[i] = read();
    dp[0][0] = 1;
    for(int i = 1; i <= n; ++i)
        for(int j = f - 1; j >= 0; --j){
            dp[i][j] = dp[i - 1][j] + dp[i - 1][(j + f - a[i] % f) % f];
            dp[i][j] %= mod;
        }
    write(dp[n][0] - 1); enter;
    return 0;
}

Remove the Substring

:给出两个字符串,其中一个为另一个子字符串(这里有不同的定义子字符串),问我们可以最多可以删除第一个字符串多长长度,任然满足第二个为子字符串,删除的只能为一个连续区间的字符串

首先我们在第一个字符串里面可以确保有一个子字符串,那么我们怎样删除呢
第一种情况:删除这个子字符串前面的一部分
第二种情况:删除这个子字符串后面的一部分
第三章情况:删除这个子字符串中间的一部分
然后需要统计最左边最先出现这个子字符串和最右边最先出现这个子字符串
#include<bits/stdc++.h>
using namespace std;
const int mx=2e5+10;
char s1[mx],s2[mx];//输入的两个字符串
int h1[mx],h2[mx];//分别统计最左边和最右边

int main()
{
    scanf("%s%s",s1,s2);
	int l1=strlen(s1);
	int l2=strlen(s2);
	int i,j;
	for(i=j=0;i<l1&&j<l2;i++)//首先统计最左边什么时候出现完整的子字符串
	  if(s1[i]==s2[j])
	   h1[j++]=i;
	  
	j=l2-1;
	for(i=l1-1;i>=0&&j>=0;i--)//再统计最后边
	  if(s1[i]==s2[j])
	   h2[j--]=i;
	
	int m1=max(h1[0],l1-1-h1[l2-1]);//因为统计了最左边,看看删除左右长度
	int m2=max(h2[0],l1-1-h2[l2-1]);//这个统计了最右边,同理
	int mm=max(m1,m2);
	for(int i=1;i<=l2-1;i++)
	mm=max(mm,h2[i]-h1[i-1]-1);//这里要注意后面为i-1
	printf("%d\n",mm); //因为i相等时,s2[i]这个字符有两次
	return 0;
}

  

 

------------恢复内容结束------------

洛谷p1685 

题意是一张图,从西到东有多条线路,你可以游览多次,但是你每次必须走不同道路,只要有一条不同于上一次条,就认为不同,求出所有方案路线总花费

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=10000;
#define int long long
int in[maxn],dist[maxn],cnt[maxn],tot,h[maxn*2],n,m,s,t0,t;
queue<int>q;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
struct node
{
    int dis,to,nxt;
}edge[2*maxn];
void add(int u,int v,int d)
{
    edge[++tot].nxt=h[u];
    edge[tot].to=v;
    edge[tot].dis=d;
    h[u]=tot;
    in[v]++;
}
void bfs( )
{
    q.push(s);cnt[s]=1;
    while(q.size()){
    int x=q.front();q.pop();
    for(int i=h[x];i;i=edge[i].nxt){
        int v=edge[i].to;
        (dist[v]+=dist[x]+cnt[x]*edge[i].dis)%=mod;
        (cnt[v]+=cnt[x])%=mod;
        in[v]--;
        if(!in[v]) q.push(v);
    }
    }
}
signed main()
{
    int u,v,d;
    n=read(),m=read(),s=read(),t=read(),t0=read();
    for(int i=1;i<=m;i++){
        u=read(),v=read(),d=read();
        if(u!=v) add(u,v,d);
    }
    bfs();
    printf("%lld\n",(dist[t]%mod+(cnt[t]-1)*t0%mod)%mod);
    return 0;
}  

csl的训练

一道拓扑排序题

https://ac.nowcoder.com/acm/contest/551/G

a1+r1k+((a1+r1k)+r2k))+(((a1+r1k)+r2k))+r3k)+...=sum

要使k最大,那么a1肯定等于0,再将k提出来,就会变k*total<=s;

total就是每个节点的值,从题目要求得知,我们得从第一个人(入度为0的那一个开始)

而total等于每个节点的值,都由前面的点决定,故拓扑排序,所以我们用0连接起所有的点,

接下来就可以得出一个入度为0的点开始拓扑

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=6e5+10;
const int mod=10000;
ll in[maxn],dist[maxn],cnt[maxn],tot,h[maxn*2],n,m,s,t0,t;
queue<ll>q;
ll read(){
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
struct node
{
    ll dis,to,nxt;
}edge[2*maxn];
void add(ll u,ll v,ll d)
{
    edge[++tot].nxt=h[u];
    edge[tot].to=v;
    edge[tot].dis=d;
    h[u]=tot;
    in[v]++;
}
ll bfs(ll s)
{
    ll ans=0;
    q.push(s);
    dist[s]=0;
    while(q.size()){
    ll x=q.front();q.pop();
    for(ll i=h[x];i;i=edge[i].nxt){
        ll v=edge[i].to;
        ll r=edge[i].dis;
        dist[v]=max(dist[v],dist[x]+r);
        in[v]--;
        if(!in[v]) q.push(v);
    }
    }
    for(ll i=1;i<=n;i++)
        ans+=dist[i];
    return ans;
}
int main()
{
    ll u,v,d,ans;
    n=read(),m=read(),s=read();
    for(ll i=1;i<=m;i++){
        u=read(),v=read(),d=read();
        add(u,v,d);
    }
    for(ll i=1;i<=n;i++){
        add(0,i,0);
    }
    ans=bfs(0);
    if(ans==0) printf("-1\n");
    else if(ans>s) printf("0\n");
    else printf("%lld\n",s/ans);
    return 0;
}

  

 

 

 

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!