南京理工大学第八届程序设计大赛(校外镜像)

偷吃糖果

Time Limit: 1000Ms

Memory Limit: 65536KB

Description

小鱼喜欢吃糖果。他有两盒糖果,两盒糖果分别仅由小写字母组成的字符串s和字符串t构成。其中'a'到'z'表示具体的某种糖果类别。他原本打算送给他喜欢的女生,但是要送给女孩子的话两盒糖果不能有差别 (即字符串s和t完全相同)。所以,他决定偷吃几块,他吃糖果的策略是每次选出一盒糖果中两个连续的同种类别的糖果,然后吃掉其中一块。 该策略可以使用多次。例如一盒糖果是'rrrjj',他可以把这盒糖果变成'rrjj'或者'rrrj'。现在你要告诉小鱼,经过他多次偷吃糖果之后,两盒糖果能否送给他喜欢的女孩子。如果可以输出'Yes',如果不行输出'No'。

Input

第一行一个T,表示T组测试数据。每组测试数据格式如下。第一行表示字符串s,第二行表示字符串t。1 ≤ T ≤ 100Each character of s, t will be between 'a' and 'z'.1 ≤ length of string s ≤ 10001 ≤ length of string t ≤ 1000

Output

对于每组测试数据,输出Yes,或者No。

Sample Input

2
rrrjj
rrrj
rj
jr

Sample Output

Yes
No

Hint

题目中的第一个样例:
第一盒糖果:rrrjj -> rrjj -> rjj -> rj
第二盒糖果:rrrj -> rrj -> rj


A:
/*
思路:
把连续相同的缩成一个字母,然后对比一下即可
hhh-2016-04-17 13:01:22
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
#include <math.h>
using namespace std;
#define lson  (i<<1)
#define rson  ((i<<1)|1)
typedef long long ll;
const int mod = 1000000009;

const int maxn = 1100;

char s1[maxn];
char s2[maxn];
char str1[maxn];
char str2[maxn];

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int tot1,tot2;
        scanf("%s%s",s1,s2);
        tot1 = tot2 =  0;
        str1[tot1++] = s1[0];
        for(int i=1; s1[i]!='\0'; i++)
        {
            if(s1[i]!=s1[i-1]) str1[tot1++]=s1[i];
        }
        tot2 = 0;
        str2[tot2++] = s2[0];
        for(int i=1; s2[i]!='\0'; i++)
        {
            if(s2[i]!=s2[i-1]) str2[tot2++]=s2[i];
        }
        if(tot1!=tot2) printf("No\n");
        else
        {
            bool flag = true;
            for(int i=0; i<tot1; i++)
            {
                if(str1[i]!=str2[i])
                {
                    flag = false;
                    break;
                }
            }
            if(flag) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

count_prime

Time Limit: 1000ms

Memory Limit: 65536KB

Description

给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的。

Input

第一行输入一个整数T(1 <= T <= 100),表示T组测试数据。接下来T行,每行3个整数a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔开。

Output

输出一个整数表示 和n互质 的数的个数。

Sample Input

2
1 10 2
3 10 5

Sample Output

5
6


C:

/*
求解区间[a,b]中与k互质的个数
首先对k进行质数分解,然后与这个因子GCD!=1则共有n/ki个.有计算重复的部分,因此利用
容斥原理:  k1+k2+k3-k1*k2-.....求出与k不互质的个数,用总的减去即可

hhh-2016-04-17 12:56:32
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
#include <math.h>
using namespace std;
#define lson  (i<<1)
#define rson  ((i<<1)|1)
typedef long long ll;
const int mod = 1000000009;
const int maxn = 100040;

ll solve(ll r,ll n)
{
    vector<int> vec;
    for(int i=2; i*i<=r; i++)
    {
        if(r%i==0)
        {
            vec.push_back(i);
            while(r%i==0)
            {
                r/=i;
            }
        }
    }
    if(r>1) vec.push_back(r);
    ll sum=0;
    for(int num=1; num<(1<<vec.size()); num++)
    {
        ll mult=1,ones=0;
        for(int i=0; i<vec.size(); i++)
        {
            if(num&(1<<i))
            {
                ones++;
                mult*=vec[i];
            }
        }
        if(ones%2) sum+=n/mult;
        else sum-=n/mult;
    }
    return n-sum;
}
int main()
{
    int n,T;
    scanf("%d",&T);
    ll l,r,x;
    while(T--)
    {
        scanf("%I64d%I64d%I64d",&l,&r,&x);
        cout << solve(x,r)-solve(x,l-1) << "\n";
    }
    return 0;
}

triple

Time Limit: 3000MS

Memory Limit: 65536KB

Description

给出一个整数n,表示1,2,...,n。从这n个数中任意选择3个不同的数字x,y,z,问x,y,z的最大公约数等于m的方案有多少种?(注意:(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)属于同一种方案)

Input

第一行输入一个整数T(1 <= T <= 100),表示有T组数据,接下来T行,每行2个整数n, m(1 <= m <= n <= 10^5)

Output

输出一个整数表示答案

Sample Input

1
5 1

Sample Output

10


D:
/*
计算[1,n]中任选3个数a,b,c   GCD(a,b,c) = k
首先C(n/m,3)能得出所有的可能,然后根据容斥原理还要减去其中一部分计算重复的:C(n/(i*m),3) (i>=2)
,至于什么时候进行什么运算,这个便能用莫比乌斯反演解决.

//printf("%I64d")导致一直WR - -
hhh-2016-04-17 16:42:03
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
#include <math.h>
using namespace std;
#define lson  (i<<1)
#define rson  ((i<<1)|1)
typedef long long ll;
const int mod = 1000000009;
const int maxn = 100040;

int tot;
ll is_prime[maxn];
ll mu[maxn];
ll prime[maxn];

void Moblus()
{
    tot = 0;
    mu[1] = 1;
    for(ll i = 2; i < maxn; i++)
    {
        if(!is_prime[i])
        {
            prime[tot++] = i;
            mu[i] = -1;
        }

        for(ll j = 0; j < tot && i*prime[j] < maxn; j++)
        {
            is_prime[i*prime[j]] = 1;
            if(i % prime[j])
            {
                mu[i*prime[j]] = -mu[i];
            }
            else
            {
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
}

ll cal(ll n,ll k)
{
    if(n < 3)
        return 0;
    if(n == 3)
        return 1;
    ll ans1 = 1;
    ll ans2 = 1;
    for(ll i = n,j = 1;i >= 1 && j <= k;i--,j++)
    {
        ans1 *= i;
        ans2 *= j;
    }
    return ans1/ans2;
}

int main()
{
    ll n,m;
    int T;
    Moblus();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%I64d",&n,&m);
        if(n < 3)
        {
            printf("0\n");
            continue;
        }
        ll all = 0;
        //cout << all <<endl;
        for(ll i = 1;i*m <= n;i++)
        {
            all += (ll)mu[i]*cal(n/i/m,3);
        }
        cout << all <<"\n";
    }
    return 0;
}


F:

sequence

Time Limit: 1000MS

Memory Limit: 65536KB

Description

将一个给定的数列,拆分成K个不降序列,每个数出现且只出现一次,且在各序列中各个数相对于原数列的相对顺序不变。如7 6 9 8 10可以拆成 7 9 10和6 8。求最小的K值。

Input

第一行输入一个整数T(1 <= T <= 100),表示接下来T组测试数据,每组两行,第一行为n,代表数列长度(1<=n<=10000)接下来一行有n个数,空格分隔(每个数<=50000)。

Output

对每组数据输出一个最小的K值。

Sample Input

2
5
7 6 9 8 10
5
5 4 3 2 1

Sample Output

2
5
/*
最长上升序列的长度等于不上升序列的最小分划
(详情自行百度)
hhh-2016-04-17 14:18:52
*/
#include <iostream>
#include <cstdlib>
#include <cstdio>

using namespace std;
int num[51000];
int dp[51000];

int Search(int l, int r, int value)
{
    if(l==r) return l;

    int mid = (l+r)/2;
    if(value>dp[mid])
        return Search(mid+1, r, value);
    else
        return Search(l, mid, value);
}

int main()
{
    int t, n, index;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i=n-1; i>=0; i--)
            scanf("%d", num+i);

        int cur = 0;
        dp[0] = 0;
        for(int i=0; i<n; i++)
        {
            if(num[i]>dp[cur])
            {
                dp[++cur] = num[i];
            }
            else
            {
                index = Search(1, cur, num[i]);
                dp[index] = num[i];
            }
        }
        printf("%d\n", cur);
    }
    return 0;
}


琪露诺的算术教室

Time Limit: 1000ms

Memory Limit: 65536KB

Description

给出一个非负整数A,将这个数字的最低位移动到最高位(原来的最高位变为次高位,次低位变成最低位),得到非负整数B,发现B恰好是A的k倍。现给出A的最低位的值n,和倍数k,求最小的非负整数B。

Input

第一行输入一个正整数T(1 <= T <= 1000),表示有T组测试数据。对于每组测试数据:输入两个整数n,k(0<=n<=9 , 0<=k<=9)。

Output

对于每组测试数据,输出一个非负整数B,若无解,请输出-1。

Sample Input

1
2 2

Sample Output

210526315789473684
G:
/*
给了你最后一以为x 和 倍数k,所以x乘以k就是b的最后一位(a的倒数第二位)
然后一直往前推。这时需要的就是解决什么时候无解。开始试了两发WR,然后直接打表
算了.
还有就是没考虑到 b=102564是并不能算一个解 TAT
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
#include <math.h>
using namespace std;
#define lson  (i<<1)
#define rson  ((i<<1)|1)
typedef long long ll;
const int mod = 1000000009;
const int maxn = 100040;
char ta[105][10005] =
{
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"-1",
"1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"2",
"210526315789473684",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"3",
"315789473684210526",
"3103448275862068965517241379",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"4",
"421052631578947368",
"4137931034482758620689655172",
"410256",
"-1",
"-1",
"-1",
"-1",
"-1",
"-1",
"5",
"526315789473684210",
"5172413793103448275862068965",
"512820",
"510204081632653061224489795918367346938775",
"-1",
"-1",
"-1",
"-1",
"-1",
"6",
"631578947368421052",
"6206896551724137931034482758",
"615384",
"612244897959183673469387755102040816326530",
"6101694915254237288135593220338983050847457627118644067796",
"-1",
"-1",
"-1",
"-1",
"7",
"736842105263157894",
"7241379310344827586206896551",
"717948",
"714285",
"7118644067796610169491525423728813559322033898305084745762",
"7101449275362318840579",
"-1",
"-1",
"-1",
"8",
"842105263157894736",
"8275862068965517241379310344",
"820512",
"816326530612244897959183673469387755102040",
"8135593220338983050847457627118644067796610169491525423728",
"8115942028985507246376",
"8101265822784",
"-1",
"-1",
"9",
"947368421052631578",
"9310344827586206896551724137",
"923076",
"918367346938775510204081632653061224489795",
"9152542372881355932203389830508474576271186440677966101694",
"9130434782608695652173",
"9113924050632",
"91011235955056179775280898876404494382022471"
};
int main()
{
    int n;scanf("%d",&n);
    while( n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int t = a*10+b;
        printf("%s\n",ta[t]);
    }
    return 0;
}

谁才是最强战舰!

Time Limit: 1000MS

Memory Limit: 65536KB

Description

依阿华来到镇守府的第一件事情,就是找大和solo!然而这并不是什么好消息,说不定,镇守府,甚至佐伯湾就这么消失了。。。于是,提督君想了一个简单的游戏,来分出她们的胜负。游戏规则如下:这里有N堆石子,每堆石子有a[i](1<=i<=N)个,每人轮流从其中的某一堆石子中拿出任意个石子(只能在其中一堆拿,不能不拿),大和先手,谁拿出了最后一个石子,谁输。若大和必胜,输出“Yamato_Saikou!”,若依阿华必胜,输出“Meidikeji_Shijiediyi!”,若两边都无法必胜,输出“Sayonara_Konosekai!”.

Input

第一行输入一个正整数T(1 <= T <= 1000),表示有T组测试数据。对于每组测试数据:第一行一个正整数,N(N<=1000),表示有N堆石子。第二行N个整数a[i](1<=a[i]<=1000),表示每堆石子的数量。

Output

若大和必胜,输出“Yamato_Saikou!”,若依阿华必胜,输出“Meidikeji_Shijiediyi!”,若两边都无法必胜,输出“Sayonara_Konosekai!”.

Sample Input

3
1
5
2
1 2
3
1 1 1

Sample Output

Yamato_Saikou!
Yamato_Saikou!
Meidikeji_Shijiediyi!

H:

/*
另类NIM游戏诶,这个是取走最后一个石子的算输

官方解:
奇异局势,所有堆的xor和==0.

假定S是非奇异局势,T是奇异局势。
一堆中石子数量>=2,表示充裕堆, =1表示孤单堆。

S0即非奇异局势下,充裕堆为0的状态
S1即非奇异局势下,充裕堆为1的状态
S2即非奇异局势下,充裕堆>=2的状态

T0即奇异局势下,充裕堆为0的状态
T2即奇异局势下,充裕堆>=2的状态

1.奇异局势的定义可知,S能转移到T,能转移到S, T只能转移到S

2.S0必败,T0必胜

3.S1必胜,因为S1只需要转移到S0即可。

4.S2必胜,T2必败。
1)T2只能转移到S1 和 S2
2)若T2转移到S1 则T2败,若T2转移到S2,S2只需要转回到T2即可。所以S2胜,T2败。

所以:
必胜态:T0,S1,S2
必败态:S0,T2

hhh-2016-04-17 14:33:20
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>
#include <math.h>
using namespace std;
#define lson  (i<<1)
#define rson  ((i<<1)|1)
typedef long long ll;
const int mod = 1000000009;

const int maxn = 1100;

int a[maxn];

int main()
{
    int t, n, index;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        int flag = 1;
        int sum = 0;
        for(int i  =1;i <= n;i++)
        {
            scanf("%d",&a[i]);
            sum ^= a[i];
            if(a[i] != 1)
                flag = 0;
        }
        if(flag)
        {
            if(n & 1)
                printf("Meidikeji_Shijiediyi!\n");
            else
                printf("Yamato_Saikou!\n");
        }
        else
        {
            if(sum)
            {
                printf("Yamato_Saikou!\n");
            }
            else
            {
                printf("Meidikeji_Shijiediyi!\n");
            }
        }
    }
    return 0;
}



water1

Time Limit: 1000MS

Memory Limit: 65536KB

Description

听说全球气候变暖,冰川融化,海水淹大地。着实好奇要融化多少冰川会淹没我的宿舍,哦不,淹没南京,反正NJUST应该总会是第一批被淹的。现将问题简化成一个二维坐标系的模型。有N个矩形块区域,每个区域有海拔(H)和宽度(W),区域按照顺序给出,比如有3个区域,第一个区域宽度为1,海拔为2,第二个区域宽度为5,海拔为6,第三个区域宽度为3,海拔为4,从图像上看就是像这样:(Y轴是海拔)8 7 6 +++++5 +++++4 ++++++++3 ++++++++2 +++++++++1 +++++++++ 123456789假设最左边和最右边都是无限高的墙。为了简化问题,假设水流下来的速度是每秒一个单位的水,并且总是往区域一降水(某沿海地区)。现在请问要淹没所有的区域至少要多少时间(秒)?淹没的定义是,所有的区域表面至少覆盖一层水。如果没有区域则至少要放一滴水。上图例子中,淹没完如下:87 wwwwwwwww6 w+++++www5 w+++++www4 w++++++++3 w++++++++2 +++++++++1 +++++++++ 123456789所以需要19秒。

Input

多CASE,测试数据以EOF结尾,对于每个CASE:第一行一个整数N(0 <= N <= 10^5)。接下去N行每行对应两个整数H(1 <= H <= 10^5),W(1 <= W <= 10^5)分别对应第N个区域的海拔和宽度。

Output

一个整数,表示所需要的时间。

Sample Input

3
2 1 
6 5
4 3

Sample Output

19

J水过:

#include <iostream>
#include <cstdlib>
#include <cstdio>

using namespace std;
const int maxn = 100100;
int h[maxn];
int w[maxn];

typedef long long ll;

int main()
{
    int n, maxh, sumw;
    ll ans;
    while(scanf("%d", &n)!=EOF)
    {
        maxh = 0;
        ans = 0;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d", h+i, w+i);
            maxh = max(maxh, h[i]);
        }
        maxh += 1;
        for(int i=0; i<n; i++)
        {
            ans +=  ( (long long)(maxh - h[i]) * w[i] );
        }
        if(n == 0) ans = 1;
        cout<<ans<<"\n";
    }

    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值