套题 ,8.23下午

1 X 国的军队(army.c/cpp/pas)
1.1 题目描述
X 国和 Y 国开战了!
作为 X 国的军事参谋,你了解到事态的严峻性。为了更好地应付敌人,你收集到了 Y
国城市中 n 个据点的信息,你打算攻破这 n 个据点!
每个据点 i 的信息由火力系数 A[i]、士兵数目 B[i]组成,作为一名具有高超预谋能力的
参谋,你当然可以借此分析情势。实际上,你分析得出,攻占一个据点 i,为了稳定己方士
兵士气,至少需要 B[i]个士兵参战,战后将会有 A[i]个士兵阵亡。
由于不停地调谴, 可用的士兵已经不多了, 于是在一个据点参战且未阵亡的士兵可能会
参加别的据点的战斗。你需要计算出攻破这 n 个据点所需要的最少的士兵数目。
然而更糟的, 一共有 T 个城市, 所以你需要将 T 个城市所需的最少士兵数目依次输出。
1.2 输入格式
第一行为一个整数 T,表示城市数目。
接下来 T 组数据。每组数据第一行包含一个数 n,表示据点数目;接下来 n 行,其中
第 i 行包含两个数,分别表示这个据点的火力系数 A[i]以及士兵数目 B[i]。
1.3 输出格式
对于每个城市输出一行,表示攻占这个城市所有据点所需要的最少士兵数目。
1.4 样例输入
2
2
4 7
1 5


3
3
1 4
4 6
3 5
1.5 样例输出
8
10
1.6 数据范围与约定
对于前 20%的数据 n<=9
对于前 40%的数据 n<=1000
对于 100%的数据 n<=100000,T<=10,1<=A[i]<=B[i]<=1000000000。
由于本题读入数据较多,建议使用较快的读入方式。

第一遍错了

#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
int f[100007];
long long tot;
int a,b;
int T,n,minn,maxn;
int main()
{
    freopen("army.in","r",stdin);
//    freopen("army.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);tot=0;minn=99999999;maxn=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            tot+=a;
            minn=min((b-a),minn);maxn=max(maxn,b);
        }        
        printf("%lld\n",max((long long )maxn,tot+minn));
    }
    return 0;
}
一个错误的代码

 

#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long 
using namespace std;
#define M  1000000007
int T,n;
LL mub[2000010];
void first(LL x)
{
    mub[1]=1;
    for(int i=2;i<=x;i++)    
        mub[i]=(mub[i-1]*i)%M;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    LL dd=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return dd;
}
LL ny(LL a, LL n)
{
    LL x,y;
    LL d=exgcd(a,n,x,y);
    if(d==1)    return (x%n+n)%n;
    else return -1;
}
LL work(LL x)
{
    LL cc=ny(mub[x],M);
    return mub[x*2]*cc%M*cc%M;
}
int main()
{
    freopen("pc.in","r",stdin);
    freopen("pc.out","w",stdout);
    scanf("%d",&T);    
    first(2000010);
    while(T--)
    {
        scanf("%d",&n);
        printf("%lld\n",work(n));
    }
    return 0;
}
AC代码

 

2 排列组合(pc.c/cpp/pas)
2.1 题目描述
T 组数据,每次给定 n,请求出下式的值,对 10^9+7 取模:

  
2.2 输入格式
第一行一个整数 T,表示数据组数。
接下来 T 行,每一行包含一个整数 n,含义如题所示。
2.3 输出格式
输出 T 行,每行包含一个整数,表示对 10^9+7 取模后的答案。
2.4 样例输入
2
1
2
2.5 样例输出
2
6
2.6 数据范围与约定
对于 30%的数据,T<=500 , n<=10000。
对于 100%的数据,T<=100000 , n<=1000000。

 数学奥赛生说:

#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long 
using namespace std;
#define M  1000000007
int T,n;
LL mub[2000010];
void first(LL x)
{
    mub[1]=1;
    for(int i=2;i<=x;i++)    
        mub[i]=(mub[i-1]*i)%M;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    LL dd=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return dd;
}
LL ny(LL a, LL n)
{
    LL x,y;
    LL d=exgcd(a,n,x,y);
    if(d==1)    return (x%n+n)%n;
    else return -1;
}
LL work(LL x)
{
    LL cc=ny(mub[x],M);
    return mub[x*2]*cc%M*cc%M;
}
int main()
{
    freopen("pc.in","r",stdin);
    freopen("pc.out","w",stdout);
    scanf("%d",&T);    
    first(2000010);
    while(T--)
    {
        scanf("%d",&n);
        printf("%lld\n",work(n));
    }
    return 0;
}
代码

 

 

3 回文(pal.c/cpp/pas)
3.1 题目描述
闲着无聊的 YGH 秒掉上面两道题之后,开始思考有趣的回文串问题了。
他面前就有一个漂浮着的字符串。显然 YGH 是会 manacher 的,于是他随手求出了这
个字符串的回文子串个数。但是他不满足于这个问题,他打算搞出一个数据结构,能够快速
求出这个字符串下标为[l,r]的子串的回文子串个数(相同的回文子串需重复计数)。但是这实
在是太简单啦,他打算考考辣鸡 YYR,可是辣鸡至极的 YYR 完全没有思路。
于是,YGH 扬长而去,在衣袖带起的一小片尘土之中,沉思的 YYR 依旧在那里。
3.2 输入格式
第一行为一个字符串 S。
第二行一个整数 T,表示询问次数。
接下来 T 行,每行两个整数 l、r,表示查询字符串 S 下标为[l,r]的子串的答案。
3.3 输出格式
输出 T 行,每行一个整数表示这个询问的答案。
3.4 样例输入
ababaab
2
1 3
3 7
3.5 样例输出
4
8
NOIP 模拟题 #2
6
3 .6 数据范围与约定
对于 20%的数据,保证 |S| , T<=500
对于 40%的数据,保证 |S| , T <=5000
对于 100%的数据,保证 |S| <=5000 , T<=100000

思路:

  首先应该是个dp,dp[i][j]表示区间【i,j】的回文子串数。

  我们再加一个数组ok[i][j] 表示 区间【i,j】是否是个回文串。

  转移方程是:f[i][j]=f[i][j-1]+f[i+1][j]-f[i+1][j-1]+ok[i][j].

#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long 
using namespace std;
bool ok[5005][5005];
int dp[5005][5005];
char s[5005];
int T,l,r,len;
bool check(int l,int r)
{
    if(ok[l][r])    return 1;
    else if(s[l]==s[r]&&check(l+1,r-1))    return 1;
            else return 0;
}
void first()
{
    for(int i=1;i<=len;i++)
    {
        dp[i][i]=1;dp[i-1][i]=2;
        ok[i][i]=1;
        if(s[i]==s[i-1])    
        {
            ok[i-1][i]=1;
            dp[i-1][i]=dp[i-1][i-1]+dp[i][i]+ok[i-1][i];
        }
    }    
    for(int k=3;k<=len;k++)
    for(int j=k,i=1;j<=len;i++,j++)
    {
        dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1];
        if(check(i,j))    dp[i][j]++;
    }
}
int main()
{
//    freopen("pal.in","r",stdin);
//    freopen("pal.out","w",stdout);
    cin>>(s+1);len=strlen(s+1);
    first();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&l,&r);
        printf("%d\n",dp[l][r]);
    }
    return 0;
}
代码

 

posted @ 2017-08-23 17:12  浪矢-CL  阅读(360)  评论(0编辑  收藏  举报