当前位置:编程学习 > C/C++ >>

SGU 537 Divisibility

   乱搞+容斥。这道题可以暴力求解出所有组合情况,然后求所有情况的公因子就可以了,但是这样的话10! * 100 会超时,我们单独考虑出现10种字母的情况。时间复杂度就会变成9!*100了,这样就可以AC了。当出现10种字母时,会有3种情况:
 
          1. 当所以字母只出现一次时,可以暴力算出,公因子只有1, 3, 9 ,然后我们发现这种情况所得的满足情况的数,的位数和固定为45,的确会是3和9的倍数。
 
          2. 根据第一种情况,可以推出,当一种字母出现4次,其他字母都只出现一次时,一定可以被3整除。。。然后暴力了几个样例,发现都只能被1,3整除。。。然后就厚颜易做图的这样写了。。。主啊,原谅我的无知吧。。。实在是证不出来了。。。。。
 
          3.然后发现剩余的情况都是只有1了。。
 
         同学YY到另一种很快的方法,那就是当使用字母小于10的时候,对于原串比如aba,则组成的情况为101*a + 10 * b。。。101和10的公因子肯定满足任意的情况,然后对于任意组合a, b  必能找到 a和b 使得 和的公因子不包含别的因子(这个也没证出来,发的题解供大家对拍吧。。。。)
 
 
#include<algorithm>  
#include<iostream>  
#include<cstring>  
#include<cstdio>  
#include<vector>  
#include<cmath>  
#include<set>  
#define LL long long  
#define CLR(a, b) memset(a, b, sizeof(a))  
  
using namespace std;  
const int N = 16;  
const int M = 4000000;  
bool isp[M];  
int p[M], cnt = 0;  
char ch[N];  
  
void get_p()  
{  
    CLR(isp, true);  
    isp[1] = isp[0] = 0;  
    for(int i = 2; i < M; i ++)  
    {  
        if(isp[i])  
        {  
            p[cnt ++] = i;  
            if(i < 4000)for(int j = i * i; j < M; j += i)  
                isp[j] = false;  
        }  
    }  
    return ;  
}  
  
vector<LL> hav, bef;  
set<LL> ans;  
set<LL>::iterator it;  
int num[1000], tot;  
  
LL 易做图(LL a, LL b)  
{  
    return b ? 易做图(b, a % b) : a;  
}  
  
void dfs(int st, LL now)  
{  
    ans.insert(now);  
    if(st >= tot) return;  
    LL tmp = 1;  
    for(int i = 0; i <= num[st]; i ++)  
    {  
        dfs(st + 1, now * tmp);  
        tmp *= bef[st];  
    }  
    return ;  
}  
  
void solve(LL dan)  
{  
    bef.clear();int tmp = 0;tot = 0;  
    for(int i = 0; (LL)p[i] * p[i] <= dan; i ++)  
    {  
        tmp = 0;  
        while(dan % p[i] == 0)  
        {  
            dan /= p[i];  
            tmp ++;  
        }  
        if(tmp) bef.push_back(p[i]), num[tot ++] = tmp;  
    }  
    if(dan > 1) bef.push_back(dan), num[tot ++] = 1;  
    ans.clear();  
    dfs(0, 1);  
    for(it = ans.begin(); it != ans.end(); it ++)  
    {  
        LL tmp = *it;  
        printf(" %I64d", tmp);  
    }puts("");  
}  
  
LL sb[30];  
int id[30], sid;  
bool vis[11];  
  
void dfs1(int st, LL now)  
{  
    if(st == sid)  
    {  
        hav.push_back(now);  
        return;  
    }  
    for(int i = 0; i < 10; i ++)  
    {  
        if(!i && !st) continue;  
        if(vis[i]) continue;  
        vis[i] = 1;  
        dfs1(st + 1, now + sb[st] * (LL)i);  
        vis[i] = 0;  
    }  
}  
  
int main()  
{  
    //freopen("in.txt", "r", stdin);  
    int t, len, cas = 1;LL ans;  
    get_p();scanf("%d", &t);  
    while(t --)  
    {  
        scanf("%s", ch);  
        len = strlen(ch);hav.clear();  
        CLR(sb, 0);sid = 0;CLR(id, -1);  
        for(int i = 0; i < len; i ++)  
        {  
            if(id[ch[i] - 'a'] < 0)  
            {  
                id[ch[i] - 'a'] = sid ++;  
            }  
        }  
        for(char i = 'a'; i <= 'z'; i ++)  
        {  
            LL tmp = 0;  
            for(int j = 0; j < len; j ++)  
            {  
                tmp *= 10;  
                if(i == ch[j]) tmp += 1;  
            }  
            if(tmp) sb[id[i - 'a']] = tmp;  
        }  
        printf("Case %d:", cas ++);  
        if(sid < 10)  
        {  
            CLR(vis, 0);  
            dfs1(0, 0);  
            ans = 0;  
            for(int i = 0; i < hav.size(); i ++)  
                ans = 易做图(ans, hav[i]);  
            solve(ans);  
        }  
        else  
        {  
            if(len == 10) puts(" 1 3 9");  
            else if(len == 13)  
            {  
                CLR(sb, 0);bool flag = 0;  
                for(int i = 0; i < len; i ++)  
                {  
                    sb[ch[i] - 'a'] ++;  
                    if(sb[ch[i] - 'a'] == 4) flag = 1;  
                }  
                if(flag) puts(" 1 3");  
                else puts(" 1");  
            }  
            else puts(" 1");  
        }  
    }  
}  

[cpp] view plaincopyprint?
#include<algorithm>  
#include<iostream>  
#include<cstring>  
#include<cstdio>  
#include<vector>  
#include<cmath>  
#include<set>  
#define LL long long  
#define CLR(a, b) memset(a, b, sizeof(a))  
  
using namespace std;  
const int N = 16;  
const int M = 4000000;  
bool isp[M];  
int p[M], cnt = 0;  
char ch[N];  
  
void get_p()  
{  
    CLR(isp, true);  
    isp[1] = isp[0] = 0;  
    for(int i = 2; i < M; i ++)  
    {  
        if(isp[i])  
        {  
            p[cnt ++] = i;  
            if(i < 4000)for(int j = i * i; j < M; j += i)  
                isp[j] = false;  
        }  
    }  
    return ;  
}  
  
vector<LL> hav, bef;  
set<LL> ans;  
set<LL>::iterator it;  
int num[1000], tot;  
  
LL 易做图(LL a, LL b)  
{  
    return b ? 易做图(b, a % b) : a;  
}  
  
void dfs(int st, LL now)  
{  
    ans.insert(now);  
    if(st >= tot) return;  
    LL tmp = 1;  
    for(int i = 0; i <= num[st]; i ++)  
    {  
        dfs(st + 1, now * tmp);  
        tmp *= bef[st];  
    }  
    return ;  
}  
  
void solve(LL dan)  
{  
    bef.clear();int tmp = 0;tot = 0;  
    for(int i = 0; (LL)p[i] * p[i] < dan; i ++)  
    {  
        tmp = 0;  
        while(dan % p[i] == 0)  
        {  
            dan /= p[i];  
            tmp ++;  
        }  
        if(tmp) bef.push_back(p[i]), num[tot ++] = tmp;  
    }  
    if(dan > 1) bef.push_back(dan), num[tot ++] = 1;  
    ans.clear();  
    dfs(0, 1);  
    for(it = ans.begin(); it != ans.end(); it ++)  
    {  
        LL tmp = *it;  
        printf(" %I64d", tmp);  
    }puts("");  
}  
  
int sb[30];  
  
int main()  
{  
    //freopen("in.txt", "r", stdin);  
    int t, len, cas = 1;LL ans;  
    get_p();scanf("%d", &t);  
    while(t --)  
    {  
        scanf("%s", ch);CLR(sb, 0);  
        printf("Case %d:", cas ++);  
        len = strlen(ch);hav.clear();  
        for(char i = 'a'; i <= 'z'; i ++)  
        {  
            LL tmp = 0;  
            for(int j = 0; j < len; j ++)  
            {  
                tmp *= 10;  
                if(ch[j] == i) tmp += 1;  
            }  
            if(tmp) hav.push_back(tmp);  
        }ans = 0;  
        if(hav.size() < 10)  
        {  
            for(int i = 0; i < hav.size(); i ++)  
                ans = 易做图(ans, hav[i]);  
            solve(ans);  
        }  
        else  
        {  
            if(len == 10) puts(" 1 3 9");  
            else if(len == 13)  
            {  
                CLR(sb, 0);bool flag = 0;  
                for(int i = 0; i < len; i ++)  
                {  
                    sb[ch[i] - 'a'] ++;  
                    if(sb[ch[i] - 'a'] == 4) flag = 1;  
                }  
                if(flag) puts(" 1 3");  
                else puts(" 1");  
            }  
            else puts(" 1");
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,