2018icpc青岛网络赛

A题

大水题,求最大连续数多少个和最小的最大连续数多少个。

最多连续个数,毫无疑问就是perfect的个数全都连续才最多。注意最少的个数是要平均分,比如一共8个其中6个perfect,分成2,2,2连续的个数才是最少的,如果有比2小的就会有比2大的,那么最小的最大的连续数就>2了

#include
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        cout<=2*m-1)
            cout<<'1'<m)
        {
            double mm=1.0*n/(n-m+1))>n/(n-m+1)?n/(n-m+1)+1:n/(n-m+1);//平分m, 一共(n-m+1)个位置
                                                                    //类似于分苹果,只能整个分
                                                                    
            cout<

也可以这样想

#include
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        cout<

H题

可以dp,可以区间修改,可以前缀和。

步数为偶数次时与初始状态相同,奇数次时与初始状态相反。

用区间修改和前缀和比较好想,每过一个点修改区间里的步数,区间修改线段树或树状数组维护,红灯步数+2,绿灯步数+1,利用奇偶数步判断状态。

dp:  样例3:11010

 2018icpc青岛网络赛_第1张图片

dp[3]所包含的所有时间为 t[0,1],t[1,2],t[2,3],t[1,2],t[2,3]和t[2,3] 即 t[0,2]+t[2,3],t[1,2]+t[2,3]和t[2,3]

其中 t[0,2],t[1,2]即dp[2],第三个t[2,3]就是判断第二个灯的状态是s[2]。

设change(i,j) 表示从i处到j处红绿灯变化的总次数, 计算第一个t[2,3]需要知道change[0,2], 如果change[0,2]是偶数,则计算t[2,3]时原先的红绿灯状态不变,反之,改变状态。 计算第二个t[2,3]亦是如此,需要知道change[1,2]。难点就在于change[0,2]与change[1,2]。

计算容易发现change[0,2]=3,change[1,2]=1;

 且通过计算其他的change[l,m](ichange[0,m]与change[1,m],..change[m-1,m]同奇偶
此时易得后前个t[2,3]的值是一样的, 都和change[1,2]的奇偶以及s[2]状态有关故后两个t[2,3]的和x为

if(change[1,2]为偶)  

      x=2*(s[2]=='1'?1:2); 

else

     x=2*(s[2]=='1'?2:1);

因为如果s[1]==1则change[1,2]=1,如果是s[1]=0,则change[1,2]=0,即是s[i]奇change[i,i+1]奇,反之亦然。

由伪代码可以得到,1->2点  s[1]奇s[2]奇,步数=2;s[1]偶s[2]偶,步数=2;s[1]奇s[2]偶,步数=1;s[1]偶[2]奇,步数=1;

所以

(i-1)->i的步数= s[i-1]==s[i]?2:1;

if-else语句合并为 

 x=2*(s[i-1]==s[i]?2:1);

由此得dp[i]

dp[i]=dp[i-1]+(i-1)*((s[i]==s[i-1])?2:1)+((s[i]=='1')?1:2);

AC代码:

#include
using namespace std;
const int maxn=100000+5;
long long dp[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string s;
        cin>>s;
        s='0'+s;         //s[i]下标从0开始,而规律是从1开始,所以在前面补一位
        memset(dp,0,sizeof dp);
        dp[1]=(s[1]=='1'?1:2); //根据第一个灯状态,得dp[1]
        for(int i=2;i

J题

两个人B,D按 按钮,灯不亮,按一下变亮,灯亮着,计数器+1,按按钮的时间点分别是a,c的整数倍,若时间点相同,则B先D后,按下按钮后倒计时器变为v+0.5(不管按钮前是多少)。

这个题可以模拟,可能因为我太弱惹2333,模拟总是超时(;´ ༎ຶ  Д ༎ຶ` ),然后就总数减去不ok的数得到ok的数......

#include 
using namespace std;
#define LL long long
const int N = 2e6+5;
LL f[N];
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        LL v, t;
        int a, b, c, d;
        scanf("%d%d%d%d%lld%lld", &a, &b, &c, &d, &v, &t);
        int n=0;
        for(int i=0;i

 

 

K题

两个数的异或小于这两个数,即看二进制最高位是否相同,相同的话肯定小于这两个数

#include 
using namespace std;
#define LL long long
const int N = 32;
int ans[N];
int main() 
{
    int T;
    scanf("%d", &T);
    while(T--)     
    {
        int n;
        scanf("%d", &n);
        memset(ans, 0, sizeof(ans));
        int x;
        while(n--)
         {
            scanf("%d", &x);
            int num = 0;
            while(x>0)
            {
                x>>=1;
                ++num;
            }
            ++ans[num];
        }
       /* for(int i=0;i

 

你可能感兴趣的:(2018icpc青岛网络赛)