台州学院第十二届校赛记录(B,C,E,H,I,J,L)

传送门:点我

题目很棒,感谢出题验题的大佬们。

细节坑不少,是好事。

还是很菜,继续加油!

B:

桃子的生日

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 344            测试通过: 43

描述

桃子这几天在收集纪念币,总共最多只有N种不同的纪念币,他已经收集了K种不同的纪念币。这不,桃子的生日快到了,他的M个小伙伴们决定送他纪念币,如何送给桃子呢?他们都同意了如下三个规则:

1. 每个人送的纪念币与其他人的都一样多;

2. 送给桃子的任意两枚纪念币种类均不同; 

3. 桃子从小伙伴那得到至少L枚的。

但他的小伙伴们不知道桃子收集了哪些纪念币。他们想尽量少花钱,所以他们想购买满足规则的最少数量的纪念币。

输入

第一行一个整数T(≤100),代表有T组数据。

对于每组数据,包含一行为四个整数N, M, K, L(1≤K≤N≤1018,1≤M,L≤1018),代表有N种不同的纪念币,M个小伙伴,桃子本来有K种不同的纪念币,最后桃子手上至少有L枚的纪念币。

输出

输出桃子的一个小伙伴赠送的最少数量的纪念币。如果不可能同时满足三个条件输出-1。

样例输入

2
20 15 2 3
10 11 2 4

样例输出

1
-1

提示

第一组数据:桃子的小伙伴每人送一枚纪念币,因为桃子原来有2种纪念币,小伙伴总共送15枚,一定有至少13枚是新的,满足题目要求且最少。

第二组数据:总共有10种不同的纪念币,而桃子的小伙伴有11个,不能满足条件2。

 

思路:

首先,提示告诉我们如果M>N是直接输出-1。

很明显可以看出K+L是要达到的个数,如果K+L > M,也是可以直接输出-1的,因为达不到。

最后直接判断每个人送满足条件的个数,会不会超过N即可。具体看代码有注释

代码:

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
const LL mod = 1e9+7;
int main()
{
    int _;
    for(scanf("%d",&_);_--;){
        LL n,m,k,l;
        scanf("%I64d%I64d%I64d%I64d",&n,&m,&k,&l);
        if(m > n){
            puts("-1");continue;
        }
        LL sum = k+l;
        if(sum > n){
            puts("-1");continue;
        }
        LL ans = (sum%m == 0)?sum/m:sum/m+1;//每个人要送的个数,保证可以满足K+L
        if(ans * m > n){//如果每个人送的总数超过了N,根据蜂巢原理必定会重复。所以不行
            puts("-1");continue;
        }
        else{
            printf("%I64d\n",ans);
        }
    }
}
/*
2
100 6 2 98
*/

 

 

C

桃子的难题

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 102            测试通过: 6

描述

taozi喜欢数学,但是遇到数学题就头疼,zdragon为了让大家高兴高兴,给taozi出了道难题:

S=∑q(1≤i≤n),由于答案可能会很大,答案对p取模。 

输入

输入第一行为测试样例组数T(1≤T≤100)。

对于每组数据第一行包含三个正整数n,q,p(1≤n,q,p≤109)。

输出

对于每组数据,输出一个S对p取模的值。

样例输入

2
3 2 100
4 511 520

样例输出

14
184

提示

对于第一个样例,21+22+23=14,对100取模,答案为14。

 

思路:

S=∑q(1≤i≤n),这玩意首先是个等比数列求和。然后取模,很容易想到套等比数列求和公式,逆元,取模。然而会出错。。因为可能在模数的意义下可能没有逆元。

实际上是等比数列二分求和处理这玩意(最近写过一样的题目所以知道怎么做)

考虑S=∑q(0≤i≤n),注意是有0.

就是1+q^1+q^2+....q^n

然后当n是奇数(感谢c_wwww指正)数的时候:

把这个式子分成前后相等长度的两部分

(p^0+p^1+..p^(n/2))+ (p^(n/2+1)+p(n/2+2)+...+p^n)

把后半部分的p^(n/2+1)提取出来。

(p^0+p^1+..p^(n/2)) * (p^(n/2+1)+1)

右边快速幂,左边递归

偶数的话去掉p^n,同样的操作去左边递归右边快速幂。

代码:

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
long long q(LL a,LL n,LL mod)
{
    LL ans = 1LL,temp = a%mod;
    while(n){
        if(n&1){
            ans=(ans*temp)%mod;
        }
        n>>=1;
        temp=(temp*temp)%mod;
    }
    return ans;
}
LL sum(LL p,LL n,LL mod)
{
    if(p==0)return 0;
    if(n==0)return 1;
    return (n&1)?(((1+q(p,n/2+1,mod))%mod*sum(p,n/2,mod)%mod)%mod):(((1+q(p,n/2+1,mod))%mod*sum(p,n/2-1,mod)+q(p,n/2,mod)%mod)%mod);
}
int main()
{
    /*
        LL a,b,p;
        while(~scanf("%lld %lld %lld",&a,&b,&p)){
                LL sum = 0;for(int i = 1 ; i <= a ; i ++){
                sum += q(b,i,p);
                sum%=p;
            }
            cout<<sum<<endl;
        }
    */
    LL a,b,p;
    int _;
    for(scanf("%d",&_);_--;){
        scanf("%lld %lld %lld",&a,&b,&p);
        LL ans = sum(b,a,p);
        printf("%lld\n",(ans+p-1)%p);
    }
}/*
2
3 2 100
4 511 520
*/

 

E:

YuYu的扑克牌游戏

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 14            测试通过: 3

描述

YuYu最近正在学习多位数的乘法,crq想考考她的学习情况,但又懒得出题,因此直接拿了一副扑克牌。扑克牌去掉了大小王和牌面值较大的牌,只留下A、2、3、4、5、6、7、8 、9,每种花色有9张牌,牌面值分别为1~9,现从中抽出n张牌,crq要求YuYu从n张牌中挑出若干张组成乘法公式a*b=c,其中a、b和c均可以由多张牌拼接而成(如1和2能拼成12,也能拼成21),但a和b最多是2位的正整数(因为YuYu害怕太大的数)。

如给定4 5 6 9四张牌,可以组成:

6*9=54

9*6=54

一个公式中同一张牌最多只能使用一次。

输入

多组数据,第一行为数据组数T(T<=100)。

每组数据第一行为正整数n(n<=36),第二行为n个正整数,表示从一副牌中抽取的牌面值,所有牌面值在1到9之间。

输出

对于每组数据,输出最多有多少种可能的公式。

样例输入

2
4
6 9 5 4
5
1 6 6 6 9

样例输出

2
4

 

思路:

注意C没限制是两位数即可

一眼感觉是36^4*100的题,实际100*100两个循环判断就行了。

交了打表代码过了。。不是很懂。

实际我操作的是 一个两位数乘以一个两位数等于一个四位数,比如说什么01*02=0004前面补个0

代码:

 

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
string change(int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8){
    string s = "";
    s += (a2+'0');
    s += (a1+'0');
    s += '*';
    s += (a4+'0');
    s += (a3+'0');
    s += '=';
    s += (a8+'0');
    s += (a7+'0');
    s += (a6+'0');
    s += (a5+'0');
    return s;
}
set<string>s;
int main(){
    int _;
    while(~scanf("%d",&_)){
        while(_--){
            s.clear();
    int n,a[40], cnt[12];
    memset(cnt,0,sizeof(cnt));
    scanf("%d",&n);
    for(int i = 0 ; i < n ; i ++){
        scanf("%d",a+i);
        cnt[a[i]]++;
    }
    int sum = 0;
    for(int i = 1 ; i < 100 ; i++){
        for(int j = 1 ; j < 100 ; j++){
            int temp = i;
            int num1 = temp%10;
            int num2 = temp/10%10;
            temp = j;
            int num3 = temp%10;//个位 
            int num4 = temp/10%10;//十位 
            
            temp = i*j;
            int num5 = temp%10;//个位 
            temp/=10;
            int num6 = temp%10;//十位
            temp/=10;
            int num7 = temp%10;//百位
            temp/=10;
            int num8 = temp%10;//千位
            
            if(num1 == 0||num3 == 0||num5 == 0)continue;
            
            if(num8 != 0){
                if(num7 == 0 || num6==0)continue;
            }else{
                if(num7!=0){
                    if(num6==0)continue;
                }
                else{
                    if(num6!=0){
                        if(num5 == 0)continue;
                    }
                }
            }
            //cout<<num8<<num7<<num6<<num5<<endl;
            if(num1 != 0)
                cnt[num1]--;
                
            if(num2 != 0)
                cnt[num2]--;
                
            if(num3 != 0)
                cnt[num3]--;
                
            if(num4 != 0)
                cnt[num4]--;
                
            if(num5 != 0)
                cnt[num5]--;
                
            if(num6 != 0)
                cnt[num6]--;
                
            if(num7 != 0)
                cnt[num7]--;
                
            if(num8 != 0)
                cnt[num8]--;
                    
            if( cnt[num1] >= 0 && cnt[num2] >= 0 &&
                cnt[num3] >= 0 && cnt[num4] >= 0 &&
                cnt[num5] >= 0 && cnt[num6] >= 0 &&
                cnt[num7] >= 0 && cnt[num8] >= 0 ){
                string ss = change(num1,num2,num3,num4,num5,num6,num7,num8);
                   s.insert(ss);
            }
            if(num1 != 0)
                cnt[num1]++;
            if(num2 != 0)
                cnt[num2]++;
            if(num3 != 0)
                cnt[num3]++;
            if(num4 != 0)
                cnt[num4]++;
            if(num5 != 0)
                cnt[num5]++;
            if(num6 != 0)
                cnt[num6]++;
            if(num7 != 0)
                cnt[num7]++;
            if(num8 != 0)
                cnt[num8]++;
        }
    }
//    for(set<string>::iterator it = s.begin() ; it != s.end();it++){
//        cout<<*it<<endl;
//    }
    printf("%d\n",s.size());
}}
}
/*

*/
View Code

 

 

H:

桃子的LCM

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 364            测试通过: 64

描述

桃子很喜欢数学,最近他对lcm(最小公倍数)非常感兴趣。小翁看到桃子在纸上写了一大堆数学公式,就想考考桃子。他给小桃出了个题:现在你手上有一个数b,对于每个1≤a≤1018,他把lcm(a,b)/a的不同值写在了纸上,他想问你,他能在纸上写几个不同的数字。

输入

第一行一个整数T(≤50),代表有T组数据。

对于每组数据,第一行一个整数b(1≤n≤1010),代表小桃手上的数b。

输出

输出一个数代表不同值的个数。

样例输入

2
1
2

样例输出

1
2

提示

 

第一个样例,b等于1,只有1个值1。

第二个样例,b等于2,只有2个值1和2。

 

思路:

打个表(a 从1到b+10 )

就能发现当a > b时候题目那个式子答案都一样。然后出现的不一样的值都是b的约数。所以题目转化成了求b的约数个数。

(首A拿到了,笑)

复杂度是O(sqrt(n))

代码:

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
int main()
{
    int n;
    scanf("%d",&n);
    while(n--){
        LL a;int sum = 0;
        scanf("%lld",&a);
        LL k = sqrt(a);
        for(int i = 1 ; i <= k; i++){
            if(a%i==0){
                sum+=2;
            }
        }
        if(k*k==a)sum--;
        printf("%d\n",sum);
    } 
    return 0;
}/*

*/

 

I:

桃子的长号

时间限制(普通/Java):2500MS/7500MS     内存限制:65536KByte
总提交: 347            测试通过: 47

描述

C++课上,老师讲到了映射map,桃子觉得映射很神奇,可以把一个串变成一个数存储,也可以把一堆很大的数字变成很小的数字。为了加深对映射的印象,桃子出了下面这个题:

桃子将给你一个长的十进制数a,包含n个1-9的数字,你有一个映射函数f可以把x变成f(x)。

你可以执行以下操作不超过1次:选择一个非空的连续子段并把里面的每个数字x映射成f(x)。例如a=1337,f(1)=1,f(3)=5,f(7)=3,你将选择区间[2,3],并把3变成f(3)=5,最终得到1557。

现在你执行了操作不超过1次,你可以得到的最大数是多少。

输入

第一行一个整数T(1≤T≤95),代表有T组数据。

对于每组数据:

第一行为一个整数n(1≤n≤2*105),为十进制数a的长度。

第二行为n个数字组成的整数a:a1a2...an(1≤ai≤9)。

第三行为9个数字f(1),f(2),...,f(9),代表映射函数f。

数据保证∑n<=106

输出

每组数据输出一行,代表桃子能得到的最大值。

样例输入

3
4
1337
1 2 5 4 6 6 3 1 9
5
11111
9 8 7 6 5 4 3 2 1
2
33
1 1 1 1 1 1 1 1 1

样例输出

1557
99999
33

 

 

思路:

记第i个数是num[i];

从前往后遍历第一个f(num[i]) > num[i]的改掉是最优的。然后一个坑的点是,继续遍历下去的时候可以是f(num[pos]) == num[pos]

举个例子

5

32314

1 4 3 7 1 1 1 1 1

这个数的第四个1要修改成为1,可以让第五位的4变成7。

代码:

 

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
char s[200011];
int main()
{

    int _;
    for(scanf("%d",&_);_--;){
        int n;
        scanf("%d %s",&n,s);
        int f[11];
        for(int i = 1; i <= 9 ;i++){
            scanf("%d",f+i);
        }
        for(int i = 0 ; i < n ; i++){
            int a = s[i] - '0';
            if(f[a] > a){
                int pos = i;
                while(f[a] >= a && pos < n){
                    s[pos] = f[a]+'0';
                    pos++;
                    a = s[pos] - '0';
                }
                break;
            }
        }
        printf("%s\n",s);
    }
}/*
3
4
1337
1 2 5 4 6 6 3 1 9
5
11111
9 8 7 6 5 4 3 2 1
5
32314
1 4 3 7 1 1 1 1 1

*/

 

 

J:

桃子的项链

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 102            测试通过: 17

描述

桃子喜欢收藏,尤其是对项链有着奇怪的要求:每颗珠子的颜色必须不同。由于各种原因,他找不到这种项链,所以他决定自己给项链涂色。

现在他手上有n种不同颜色的涂料,项链(环形)上有n颗珠子,他想知道他有多少种不同的涂法。若一条项链能通过绕中心旋转或翻转而变成另一个项链,则认为是同一种涂法。

输入

输入第一行为测试样例组数T(1<=T<=10000)。

对于每组数据包含一个正整数n(1<=n<=106),代表不同颜色的涂料种数或珠子数目。

输出

对于每组数据,输出一个整数代表有多少种不同的涂法。结果对109+7取模。

样例输入

2
3
4

样例输出

1
3

 

思路:

打表之后发现是(n!)/2。猜了2发(n+1)*n/2。。。。老老实实打表吧。

n= 1,2时候需要另外判断。(我是存数组然后直接输出)

代码:

 

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
const LL mod = 1e9+7;
LL a[1000011];
int main()
{
    a[0] = a[1] = a[2] = 1;
    for(int i = 3 ; i <= 1000000 ; i++){
        a[i] = (a[i-1] * i)%mod;
    }
    int _;
    for(scanf("%d",&_);_--;){
        int n;
        scanf("%d",&n);
        cout<<a[n-1]<<endl;
    }
}
/*
4
3
4
5
6
*/

 

L:

桃子的幸运彩票

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 172            测试通过: 23

描述

最近桃子爱上了博彩,一天他买了一张彩票,上面印着带有n个数字的序列a1a2a3...an

如果一张彩票是幸运的,当且仅当其满足如下全部条件:

1. 序列能被恰好分成不相交的至少2段;

2. 每一段区间[l,r]的和都是相同的。

请你帮助桃子判断他手上的彩票是不是幸运的。

例如123426是幸运的,它可以分为3段,123、42和6,1+2+3=4+2=6。

不相交就是序列的每个数字恰好属于一个段。

输入

第一行一个整数T(≤100),代表有T组数据。

对于每组数据,第一行一个整数n(2≤n≤100),代表彩票中数字序列的位数。

第二行为一个长度为n的数字序列a1a2a3...an(0≤ai≤9)。

输出

如果这张彩票是幸运的,输出YES,否则输出NO。

样例输入

2
5
73452
4
1248

样例输出

YES
NO

提示

第一个样例:能分成3段,7、34和52,7=3+4=5+2。

第二个样例:不能分出。

 

思路:

求个前缀和,暴力枚举每个区间可能的和,因为a_i都是很小的!!之后看看看看能不能划分就行了。

坑点:如果所有的数都是0,也是可以的。被这个坑了。

代码:

#include<bits/stdc++.h> 
using namespace std;
#define LL long long
#define INF 2000000000
#define eps 1e-8
#define pi  3.141592653589793
int main()
{

    int _;
    for(scanf("%d",&_);_--;){
        int n;
        scanf("%d",&n);
        string s;cin>>s;
        int a[101],flag = 0;
        int sum[111];
        memset(sum,0,sizeof(sum));
        for(int i = 0 ; i < n ; i++){
            a[i] = s[i] - '0';
            if(i == 0)sum[i+1] = a[i];
            else sum[i+1] = sum[i]+a[i];
        }
        if(sum[n] == 0){
            puts("YES");continue;
        }
        for(int i = 0; i < sum[n]; i ++){
            int pos = 0;
            for(int j = 1 ; j <= n ; j++){
                int nowsum = sum[j] - sum[pos];
                if(nowsum == i){
                    pos = j;
                //    printf("%d %d\n",i,pos);
                }
            }
            if(pos == n || sum[pos] == sum[n]){
                flag = 1;
                break;
            }
        }
        flag ? puts("YES"):puts("NO");
    }
}/*
4
20
00101000021000200100
5
73452
4
1248
8
10101000

1~10

*/

 

posted on 2019-06-09 17:30  Esquecer  阅读(465)  评论(0编辑  收藏  举报

导航