西南科技大學第十六屆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
*/

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章