皮皮J系列 1382-1384

皮皮J坐车

Description

皮皮J每天都会在校门口等小白.有一天它发现:有n个男生,m个女生排成两队,司机每一时刻从两个队伍的最前端抽一个人上车.问总共有多少个上车方案. 
由于总的方案数较大,将答案mod 1e9+7 

Input

输入数据的第一行有一个整数T,表示有T组测试数据。 
每组数据有一行只包含n,m 
T <= 200,n,m <= 100000 

Output

输出一个整数,表示总的方案数 
每组测试数据输出一行。 

Sample Input
2
2 1
2 2
Sample Output
3
6
Hint
对于样例2:假设n个人的编号为{a,b},m个人的编号为{c,d} 
总的方案为{a,b,c,d},{a,c,b,d},{a,c,d,b}.{c,a,b,d},{c,a,d,b},{c,d,a,b}. 

PS:组合数:总共n+m个位置,从中任意取n个位置依次把第一个队列中的人放入.剩下m个位置放法固定:第二队的人从头开始依次放入.

或者打个表发现是 C(m+n,n) .

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
#define Mod 1000000007
ll gcd(ll a, ll b, ll &x, ll &y){
    if (b == 0){
        x = 1, y = 0;
        return a;
    }
    ll  q = gcd(b, a % b ,y ,x);
    y -= a / b * x;
    return q;
}
ll ni(ll m,ll n) {
    ll x = 0, y = 0;
    gcd(n, m, x, y);
    if(y > 0) return y;
    else return n + y;
}
ll C(ll a,ll b){
    ll num1 = 1, num2 = 1;
    for(int i = a - b + 1; i <= a; i++){
        num1 = (num1 * i) %Mod;
    }
    for(int i = 1;i <= b; i++){
        num2 = (num2 * i) %Mod;
    }
    cout << (num1 * ni(num2, Mod)) %Mod << endl;
}
int main() {
    int m, n, T;
    cin >> T;
    while(T--) {
        cin >> m >> n;
        C(m + n, n);
    }
    return 0;
}

皮皮J与中二

Description

皮皮J平时很爱说些中二的话,有一天上课皮皮J突然喊到 
“爆裂吧,现实!破碎吧,精神!Banishment this world !” 
于是皮皮J当场被老师点名提问,问题如下 
给出字符串S,找到出现次数最多的子串.若有多解 输出长度最长的.若还有多解,输出字典序最小的. 

Input

输入数据的第一行有一个整数T,表示有T组测试数据。 
每组数据只有一行,代表字符串S 
总的字符串的长度不会超过1e5 

Output

输出满足条件的子串

Sample Input
2
cnadna
abababab


Sample Output

na
ab
Hint
例如s=xycabdxyab 
子串{x},{y},{a},{b},{xy},{ab}都出现两次 
{x,y},{a,b}长度为2 {ab}字典序较小 所以输出ab. 

思路:我的思路是后缀数组,求出height数组后,每 两个0之间最小的数代表相同长度,个数代表次数。

//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define per(i, a, n) for(int i = n - 1; i >= a; i--)
const int maxn = (int)1e5+10;
const int inf = 0x3f3f3f3f;
struct SuffixArray {
    char s[maxn];
    int sa[maxn], rank[maxn], height[maxn];
    int t1[maxn], t2[maxn], c[maxn], n;
    void build_sa(int m) {
        n = strlen(s) + 1;s[n - 1] = 0;
        int *x = t1, *y = t2;
        rep(i, 0, m)  c[i] = 0;
        rep(i, 0, n) c[x[i] = s[i]]++;
        rep(i, 1, m) c[i] += c[i-1];
        per(i, 0, n) sa[--c[x[i]]] = i;
        for(int k = 1; k <= n; k <<= 1) {
            int p = 0;
            rep(i, n - k, n) y[p++] = i;
            rep(i, 0, n) if(sa[i] >= k) y[p++] = sa[i] - k;
            rep(i, 0, m) c[i] = 0;
            rep(i, 0, n) c[x[y[i]]]++;
            rep(i, 1, m) c[i] += c[i - 1];
            per(i, 0, n) sa[--c[x[y[i]]]] = y[i];
            swap(x, y);
            p = 1, x[sa[0]] = 0;
            rep(i, 1, n)
            x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i-1] + k] ? p - 1 : p++;
        }
    }
    void build_height(){
         int j, k = 0;
         rep(i, 0, n) rank[sa[i]] = i;
         rep(i, 0, n) {
            if(k) k--;
            j = sa[rank[i] - 1];
            while(s[i + k] == s[j + k])k++;
            height[rank[i]] = k;
        }
    }
    void print(int cnt, int ans,int len) {
        if(cnt == 1) {printf("%s\n",s);return;}
        rep(i, sa[ans], sa[ans] + len) printf("%c",s[i]);printf("\n");


    }
    void solve() {
        int l = strlen(s);
        int tcnt = 1, cnt = 1, tlen = inf, len = inf, ans = 1;
        height[l + 1] = 0;
        rep(i, 1, l + 2) {
            if(height[i] != 0) tcnt++, tlen = min(tlen, height[i]);
            else {
                if(tcnt > cnt){cnt = tcnt, len = tlen, ans = i - 1;}
                if(tcnt == cnt && tlen > len){len = tlen, ans = i - 1;}
                tcnt = 1, tlen = inf;
             }
        }
        print(cnt, ans, len);
    }
}sa;
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%s", sa.s);
        sa.build_sa(128);
        sa.build_height();
        sa.solve();
    }
    return 0;
}

皮皮J与本田翼


Time Limit:1000MS  Memory Limit:65536K
Total Submit:53 Accepted:12

Description

皮皮J作为本田翼的忠实粉丝,决定送给本田翼一份礼物. 
它知道本田翼喜欢:只包含若干个数字0和若干个数字k的正数. 
并且这个正数要为n的倍数.皮皮J不想这个数字太大, 
所以它要你找到满足以上条件中最小那个数. 

Input

输入数据的第一行有一个整数T,表示有T组测试数据。 
每组数据只有一行,代表数字n和数字k 
T <= 20,1 <= n <= 100000. 1 <= k <= 9 

Output

输出满足要求的数
Sample Input

2
5 2
7 4
Sample Output

20
4004

思路:直接bfs爆long long .用同余定理剪枝,一个个存。

#include <iostream>  
#include <cstdio>  
#include <queue>  
using namespace std;  
typedef long long ll;  
const int maxn = (int)1e6 + 10;  
bool used[maxn];  
int check(string m, const int n){  
    int t = 0;  
    for(int i = 0; i < (int)m.size(); i++){  
        t = (m[i] - '0' + t * 10) % n;  
    }  
    return t;  
}  
void bfs(int n, string k) {  
    fill(used, used + n + 1, false);  
    queue<string> q;  
    q.push(k);  
    while(!q.empty()) {  
        string m = q.front();  
        q.pop();  
        int chAns = check(m, n);  
        if(chAns == 0){  
            cout << m << endl;  
            break;  
        }  
        else {  
            if(used[chAns] == false){  
                q.push(m + "0");  
                q.push(m + k);  
                used[chAns] = true;  
            }  
        }  
    }  
}  
int main() {  
    int T, n; 
    string c;  
    cin >> T;  
    while(T--) {  
       cin >> n >> c;  
       bfs(n, c);  
    }  
    return 0;  
}  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值