SRM540

250
ImportantSequence
题意:告诉你相邻两数的操作符和运算结果,求有多少满足要求的正整数序列

分析:固定了第一个数,答案就固定,由于有每个数都是正整数的限制,因此可以把限制都转移到第一个数上,把每个数用第一个数表示,就可以得到一系列不等式,解一下即可

550
RandomColoring
题意:定义颜色为(R,G,B)的三元祖,给定一个初始颜色,按照某种规则生成等概率生成下一种颜色,问最后一种颜色和第一种颜色仍然满足这种规则的概率

分析:由于数据范围都只有50,可以考虑暴力dp,复杂度显然事 O(n7) 无法满足,但计算dp[i][j][k]就相当于求三维空间中一个长方体中的所有数的和,于是可以可以求一个三位前缀和来搞;
注意求这个前缀和需要for三次(最后一维不同即可),而求区间和需要一个容斥,具体来说就是sum((xl,xr],(yl,yr],(zl,zr])是二维形式的推广

950
ProductQuery
题意:给出若干个区间乘积mod10的结果,求有多少个元素<10的非负整数数列

假如把10改成任意一个质数,那么就可以求逆元,意味着算pro[l,r]==x方案可以让[l,r-1]的数任选,前面一个数确定了最后一个数就确定了
本题稍微复杂一些,有多个区间,不过我们只关心右端点重合的那些区间,只需要把这些区间按照左端点从小到大排序,然后把大区间拆掉即可

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <typeinfo>
#include <fstream>

using namespace std;
typedef long long LL;
typedef pair<int,int>pi;
const int M=1e9+7;
inline void up(int &x,int y){
    x+=y;if(x>=M)x-=M;
}
class ProductQuery {
    public:
    int notzero[222];
    vector<pi>V[222];
    int pw[222];
    int dp[222];
    int cal(int a,int b,int p){//ret*a%p==b
        for(int i=1;i<p;i++)if(i*a%p==b)return i;
    return -1;
    }
    int solve(int N,vector<int>ql,vector<int>qr,vector<int>res,int p){
    int q=res.size();
    pw[0]=1;
    for(int i=1;i<=N+2;i++)pw[i]=1LL*pw[i-1]*(p-1)%M;
        for(int i=0;i<q;i++){
        res[i]=res[i]%p;
    }
    memset(notzero,0,sizeof(notzero));
    for(int i=0;i<q;i++){
        if(res[i]){
            for(int j=ql[i];j<=qr[i];j++)notzero[j]=1;
        }
    }
    //
    dp[0]=1;
    for(int i=1;i<=N+1;i++){
        dp[i]=0;
        if(notzero[i])continue;
        for(int j=0;j<i;j++){
            if(dp[j]){
                bool flag=1;
                for(int k=0;k<q;k++){
                    if(!res[k]&&ql[k]>j&&qr[k]<i){
                        flag=0;
                        break;
                    }
                }
                if(flag){
                    int cnt=0;
                    for(int tmp=j+1;tmp<i;tmp++)if(!notzero[tmp])cnt++;
                    up(dp[i],1LL*pw[cnt]*dp[j]%M);
                }
            }
        }
    }
    if(!dp[N+1])return 0;
    for(int i=1;i<=N;i++)V[i].clear();
    for(int i=0;i<q;i++)if(res[i])V[qr[i]].push_back(pi(ql[i],res[i]));
    int det=0;
    for(int i=N;i>=1;i--){
        if(!notzero[i]||!V[i].size())continue;
        sort(V[i].begin(),V[i].end());
        for(int j=V[i].size()-2;j>=0;j--){
            if(V[i][j].first==V[i][j+1].first){
                if(V[i][j].second!=V[i][j+1].second)return 0;
            }
            else{
                int t=cal(V[i][j+1].second,V[i][j].second,p);//cal(a,b,p)*a==b%p
                V[V[i][j+1].first-1].push_back(pi(V[i][j].first,t));
            }
        }
        det++;
    }
    int tot=0;
    for(int i=1;i<=N;i++)if(notzero[i])tot++;
    //if(p==5)printf("tot=%d det=%d\n",tot,det);
    int ans=1LL*pw[tot-det]*dp[N+1]%M;
    return ans;
    }    
    int theInput(int N, vector<int> Qfrom, vector<int> Qto, vector<int> output) {
    for(int i=0;i<Qfrom.size();i++){
        Qfrom[i]++,Qto[i]++;
    }
    return 1LL*solve(N,Qfrom,Qto,output,2)*solve(N,Qfrom,Qto,output,5)%M;   
        return 0;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值