码迷,mamicode.com
首页 > 其他好文 > 详细

WannaflyUnion每日一题

时间:2017-02-21 00:49:56      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:iostream   每日   break   排序   math   inf   prime   ...   tar   

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

1、

http://www.spoj.com/problems/KAOS/

题意:给定n个字符串,统计字符串(s1, s2)的对数,使得s1的字典序比s2的字典序要大,s1反一反(abc->cba,记为s1’)比s2’的字典序要小。

做法:先把字符串排序,当我们把s[i]当成题意中的s1的时候,j > i,s[j]是不用管的,那我们只需要用Trie树按序插入s‘,然后统计答案。

技术分享
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <time.h>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
#define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL INF = (1uLL << 63) - 1;
const LL mod = 1000000007;
const int N = 150 + 5;
const double Pi = acos(-1.0);
const int maxn = 1e5 + 5;
int trie[maxn << 4][27];
int cnt[maxn << 4];
int tol = 0;
struct node{
    char s[11];
    bool operator < (const node & a)const{
        return strcmp(a.s,s) > 0;
    }
}S[maxn];
int sum(int x) {
    int len = strlen(S[x].s);
    int now = 0;
    int res = 0;
    for(int i = len - 1; i >= 0; i--) {
        int id = S[x].s[i] - a;
        for(int j = id + 1; j < 26; j++) {
            res += cnt[trie[now][j]];
        }
        now = trie[now][id];
    }
    for(int i = 0; i < 26; i++)res += cnt[trie[now][i]];
    return res;
}
int is(int x) {
    int len = strlen(S[x].s);
    int now = 0;
    for(int i = len - 1; i >= 0; i--) {
        int id = S[x].s[i] - a;
        if(!trie[now][id]) {
            trie[now][id] = ++tol;
        }
        now = trie[now][id];
        ++cnt[now];
    }
    return sum(x);
}

int main() {
#ifdef local
    freopen("in", "r", stdin);
    //  freopen("w","w",stdout);
#endif
   // ios::sync_with_stdio(false);
  //  cin.tie(0);
    int n;
    LL ans = 0;
    scanf("%d",&n);
    for(int i = 0; i < n; i++)scanf("%s",S[i].s);
    sort(S,S+n);
    for(int i = 0; i < n; i++) {
        ans = ans + is(i);
    }
    printf("%lld\n",ans);
}
KAOS

2、

http://www.spoj.com/problems/STARSBC/

题意:一个圆上有n个等分点,现在从一个点出发,指定k,不停地隔k个点连边(样例请看link),问有多少种不同的方法,使得所有的点都被连起来。两种情况是一样的,当且仅当他们旋转若干角度以后是一样的。

做法:要能把所有点连起来那么gcd(k,n)肯定等于1,因为要把所有点连起来也就表示 k * x % n 能得到0 - n - 1所有值,一开始x为0时,k * x % n = 0,如果找到一个y使得k * y % n  = 0,那就会陷入一个循环了,如果gcd(k,n)等于c,那k * n / c % n是等于0的,也就是说当点移动了n / c次后它就会陷入循环,很明显c取1的时候才能走完所有点,那这题就是要求出gcd(x,n)==1,且x < n的所有x,但是要去掉重复的,什么时候两个情况会一样呢。假如两个k分别取x , y,当x + y等于n的时候这两种情况就会一样了,这个画图看一下就行了,证明略,gcd(x,n) == gcd(n - x, n)这个结论也好推,所以当gcd(x,n)等于1那gcd(n - x,n)也等于1,那答案就等于欧拉(n) / 2.

技术分享
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <time.h>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
#define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL INF = (1uLL << 63) - 1;
const LL mod = 1000000007;
const int N = 150 + 5;
const double Pi = acos(-1.0);
const int maxn = 1e5 + 5;
int prime[maxn];
bool vis[maxn];
int tol;
void init() {
    for(int i = 2; i < maxn; i++) {
        if(!vis[i])prime[tol++] = i;
        for(int j = 0; j < tol && i * prime[j] < maxn; j++){
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0)break;
        }
    }
}
int main() {
#ifdef local
    freopen("in", "r", stdin);
    //  freopen("w","w",stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    init();
    int n;
    while(~scanf("%d", &n)) {
        int ans = n;
        int cnt = 0;
        while(cnt < tol && prime[cnt] * prime[cnt] <= n) {
            if(n % prime[cnt] == 0) {
                ans -= ans / prime[cnt];
                while(n % prime[cnt] == 0)n /= prime[cnt];
            }
            cnt++;
        }
        if(n > 1) {
            ans -= ans / n;
        }
        ans >>= 1;
        printf("%d\n", ans);
    }
}
STARSBC

3、

http://www.spoj.com/problems/ODDDIV/

题意:给出一个正奇数K,两个正整数low,high。有多少整数属于[low, high],且包含K个因子。

做法:K是正奇数,表示n = p1 ^ m1 * p2 ^ m2 * ... * pk^mk,约数个数是(m1+1)*(m2+1)*...*(mk+1)那m肯定是偶数,所以我们可以bfs拓展一下,把k所有情况都跑出来,这样的数不会很多,数量在1e6左右,跑出来之后排序,二分结果就行了

技术分享
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <time.h>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
#define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL INF = (1uLL << 63) - 1;
const LL mod = 1000000007;
const int N = 150 + 5;
const double Pi = acos(-1.0);
const int maxn = 1e5 + 5;
int prime[maxn];
bool vis[maxn];
int tol;
void init() {
    for(int i = 2; i < maxn; i++) {
        if(!vis[i])prime[tol++] = i;
        for(int j = 0; j < tol && i * prime[j] < maxn; j++) {
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0)break;
        }
    }
}
vector<LL>A[maxn];
struct node {
    int h;
    LL Num;
    int _k;
};
queue<node>Q;
void bfs() {
    node start = (node) {
        -1, 1, 1
    };
    A[1].PB(1);
    Q.push(start);
    while(!Q.empty()) {
        node now = Q.front();
        Q.pop();
        for(int i = now.h + 1; i < tol; i++) {
            LL p = prime[i];
            LL F = p * p;
            LL die = 1;
            int num;
            for(num = 2; ; num += 2) {
                die *= F;
                if(die  <= 10000000000LL / now.Num && now._k * (num + 1) <= 100000) {
                    A[now._k * (num + 1)].PB(now.Num * die);
                    Q.push((node) {
                        i, now.Num * die, now._k * (num + 1)
                    });
                } else break;
            }
            if(num == 2)break;
        }
    }
}
bool vi[maxn];
int k;
int bs(LL x) {
    int l = 0, r = A[k].size();
    while(l + 1 < r) {
        int mid = (l + r) >> 1;
        if(A[k][mid] <= x) {
            l = mid;
        } else r = mid;
    }
    while(l >= 0 && A[k][l] > x) {
        l--;
    }
    return l;
}
int main() {
#ifdef local
    freopen("in", "r", stdin);
    //  freopen("w","w",stdout);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    init();
    bfs();
    int T;
    cin >> T;
    while(T--) {
        LL l, r;
        cin >> k >> l >> r;
        if(!vi[k]) {
            sort(A[k].begin(), A[k].end());
            vi[k] = 1;
        }
        cout<< upper_bound(A[k].begin(), A[k].end(), r) -upper_bound(A[k].begin(), A[k].end(), l - 1)<<endl;;
    }
}
ODDDIV

 

WannaflyUnion每日一题

标签:iostream   每日   break   排序   math   inf   prime   ...   tar   

原文地址:http://www.cnblogs.com/scau-zk/p/6422122.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!