西南科技大学第十六届ACM程序设计竞赛暨绵阳市邀请赛(A 打表找规律,B 组合数学 C 简单构造 D 状压dp E 唯一分解处理大LCM)

题目链接

A-找规律

做法:这题根据网友的做法,对给的两个样例进行最简单的位置变化  变化8次发现 两个的样例答案都是对的上的,于是盲搞了一发,AC,原理不知。。大概跟循环节有关吧。

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
 
int a[20],pos[20],pos1[20],b[20];
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    string s;
    while(cin>>s){
        if(s[0]=='A')a[1]=1;
        else if(s[0]=='J')a[1]=11;
        else if(s[0]=='Q')a[1]=12;
        else if(s[0]=='K')a[1]=13;
        else if(s=="10")a[1]=10;
        else a[1]=s[0]-'0';
        pos[a[1]]=1;
        for(int i=2;i<=13;i++){
            cin>>s;
            if(s[0]=='A')a[i]=1;
            else if(s[0]=='J')a[i]=11;
            else if(s[0]=='Q')a[i]=12;
            else if(s[0]=='K')a[i]=13;
            else if(s=="10")a[i]=10;
            else a[i]=s[0]-'0';
            pos[a[i]]=i;
        }
        for(int i=1;i<=13;i++){
            cin>>s;
            if(s[0]=='A')a[i]=1;
            else if(s[0]=='J')a[i]=11;
            else if(s[0]=='Q')a[i]=12;
            else if(s[0]=='K')a[i]=13;
            else if(s=="10")a[i]=10;
            else a[i]=s[0]-'0';
            pos1[i]=pos[a[i]];
        }
 
        int cnt=8;
        while(cnt--){
            for(int i=1;i<=13;i++)b[i]=a[pos1[i]];
            for(int i=1;i<=13;i++)a[i]=b[i];
        }
        for(int i=1;i<=13;i++){
            if(a[i]==1)cout<<"A ";
            else if(a[i]==11)cout<<"J ";
            else if(a[i]==12)cout<<"Q ";
            else if(a[i]==13)cout<<"K ";
            else cout<<a[i]<<' ';
        }
        cout<<endl;
    }
    return 0;
}

B-签到题

做法:这我是瞎分析了几发过的,看看完美的解释:来自:博客

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const ll mod=1e9+7;
const int N=1e6+10;
ll dp[N];
ll powmod(ll a,ll b)
{
    ll res=1;
    for(;b;b>>=1){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
    }
    return res;
}
int main()
{
    ll n;
    dp[1]=1;
    for(int i=2;i<N;++i) dp[i]=dp[i-1]*i%mod;
    while(~scanf("%lld",&n))
    {
        if(n<=1){
            puts("0");
            continue;
        }
        ll ans=dp[n]*n%mod*(n-1)%mod*powmod(2,mod-2)%mod;
        printf("%lld\n",ans);
    }
}

C-救救AR

题意:构造含有n个AR子序列的字符串,长度不能超过n

做法:n<=3 无解   n>3  两个A  其余全选R  第一个A放在第一位,第二个A放在倒数第三位即可。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const ll mod=1e9+7;
const int N=1e5+10;
char s[N];
int main()
{
    int n=read();
    if(n<=3){
        puts("-1");
    }
    else{
        s[1]='A';
        for(int i=2;i<=n;++i) s[i]='R';
        s[n-2]='A';
        printf("%s",s+1);
    }
}

D-ar采蘑菇

做法:k很小,考虑状压做法 dp[i][j][sta] 代表 i行j列 状态sta能否到达 。

sta的二进制1代表某种走法 使用过。注意这里的K种可以重复利用。很妙的一个状压dp

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10;
int dp[N][N][N];
int n,m,k;
char s[N];

pair<int,int>G[7];
int run(int x)
{
    int ans=0;
    while(x)
    {
        if(x&1) ans++;
        x=x/2;
    }
    return ans;
}
int main()
{
    int _;scanf("%d",&_);while(_--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<k;++i){
            scanf("%s",s+1);
            G[i].first=G[i].second=0;
            int len=strlen(s+1);
            for(int j=1;j<=len;++j) if(s[j]=='U') G[i].first++;
            else G[i].second++;
        }
        memset(dp,0,sizeof(dp));
        dp[0][0][0]=1;

        for(int i=0;i<=m;++i){
            for(int j=0;j<=n;++j){
                for(int sta=0;sta<(1<<k);++sta){
                    for(int id=0;id<k;++id){
                        int x=i-G[id].first,y=j-G[id].second;
                        if(x<0||y<0||x>m||y>n) continue;
                        if((sta>>id)&1){
//                            if(dp[x][y][sta^(1<<id)]){
//                                printf("x:%d y:%d i:%d j:%d sta:%d\n",x,y,i,j,sta);
//                            }
                            dp[i][j][sta]|=dp[x][y][sta^(1<<id)];
                            dp[i][j][sta]|=dp[x][y][sta];
                        }
                    }
                }
            }
        }

        int ans=0;

        for(int sta=0;sta<(1<<k);++sta){
            if(dp[m][n][sta]) ans=max(ans,run(sta));
        }

        printf("%d\n",ans);
    }
}

E-呼兰河传

做法:选择所有的数 就能得到最大的LCM  朴素的求LCM就是n次枚举  边维护GCD  边维护LCM

但是n有1e5  会超时,由于有取模操作,考虑对每个数进行唯一分解,每个素数保存某个位置i的最大次幂即可。接着对每个素数进行快速幂的 就可以避免大数问题啦

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const ll mod=1e9+9;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll powmod(ll a,ll b) {ll res=1;a%=mod;
assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}


const int N=1e6+10,M=1e5+10;
int a[N],n;
int vs[M],p[M],len,mx;
void init()
{
    for(int i=2;i<=mx;++i){
        if(!vs[i]) p[++len]=i;
        for(int j=1;j<=len&&i*p[j]<=mx;++j){
            vs[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }
    //printf("len:%d\n",len);
    //for(int i=1;i<=10;++i) printf("%d\n",p[i]);
}


int mp[M];

int main()
{


    n=read();
    rep(i,1,n) a[i]=read(),mx=max(mx,a[i]);
    init();
    sort(a+1,a+1+n);
    n=unique(a+1,a+1+n)-a-1;


    rep(i,1,n) {

        for(int j=1;j<=len;++j){
            if(p[j]>a[i]) break;
            if(a[i]%p[j]==0){
                int num=0;
                while(a[i]%p[j]==0) num++,a[i]/=p[j];
                mp[p[j]]=max(mp[p[j]],num);
            }
        }

    }

    ll ans=1;
    for(int i=2;i<=mx;++i){
        //printf("fir:%d :se:%lld\n",now.first,now.second);
        ans=(ans*powmod(i,mp[i]))%mod;
    }
    printf("%lld\n",ans);
}
/*
3
15 6 12
*/

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/106910435