Advertisement

2018 CCPC 女生赛题解

阅读量:

A题 口算训练 HDU 6287

题目要求:
包含 T 组测试用例,
每个测试用例提供一个长度为n的序列a[i]并伴随m次查询。
每次查询会指定l、r和d三个数值,
并询问该序列在区间[l, r]内的乘积是否能被d整除。
数据范围如下:
T的取值范围是从1到10之间。
n和m的最大值均不超过一百万。
ai的取值范围是从一到十万。
l和r满足条件:一≤l≤r≤n。
d的取值范围是从一到十万。

输入样例:

复制代码
    1
    5 4
    6 4 7 2 5
    1 2 24
    1 3 18
    2 5 17
    3 5 35

输出样例:

复制代码
    Yes
    No
    No
    Yes

思路:采用质因数分解的方式(单纯依赖gcd反复判断每次的结果会导致超时)。具体而言:
将vector[j](j为质因子)用于存储a[i]可被分解出的质因子及其对应的下标i:通过vector[j].push_back(i);来记录。
例如,在处理a[i]=12时,在j=2的情况下将两次推入v[2].push_back(1),此时经过两次除以2后得到a[i]=3;接着在j=3的情况下再推入v[3].push_back(1),此时经过除以3后得到a[i]=1。(此时有a[i]=2×2×3)
这样就能完成整个序列的质因数分解并存储到对应的vector中。

ac代码:

复制代码
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h> 
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int maxn = 100010;
    vector<int> v[maxn];
    
    bool d_judge(int l, int r, int d)
    {
    	int cnt, tmp;
    	for(int i = 2; i * i <= d; i++)
    	{
    		cnt = 0;
    		while(d % i == 0)
    		{
    			cnt++;
    			d /= i;
    		}
    		if(cnt > 0)
    		{
    			tmp = upper_bound(v[i].begin(), v[i].end(), r) - lower_bound(v[i].begin(), v[i].end(), l);
    			if(tmp < cnt) return false;
    		}
    	} 
    	if(d > 1){//
    		tmp = upper_bound(v[d].begin(), v[d].end(), r) - lower_bound(v[d].begin(), v[d].end(), l);
    		if(tmp < 1) return false;
    	}
    	return true;
    }
    
    int main()
    {
    int t, n, m, x, l, r, d;
    scanf("%d", &t);
    while(t--)
    {
    		scanf("%d %d", &n, &m);
    		for(int i = 0; i < maxn; i++)
    			v[i].clear();//注意这一步 
    		for(int i = 1; i <= n; i++)
    		{
    			cin>>x;
    			for(int j = 2; j * j <= x; j++)
    			{
    				while(x % j == 0)
    				{
    					v[j].push_back(i);
    					x /= j;
    				} 
    			}
    			if(x > 1) v[x].push_back(i); //注意 x可能本身为一个质因子
    		}
    		for(int i = 1; i <= m; i++)
    		{
    			cin>>l>>r>>d;
    			if(d_judge(l, r, d))
    				printf("Yes\n");
    			else	printf("No\n");
    		}		
    	} 
    	
    return 0;
    }

K题 CCPC直播 HDU 6297

题目大意:
有T组样例,每次会输入一组评测记录,然后要求将它改为符合要求的格式输出,从左至右依次是排名rank(3像素),队名S(16像素),题号prob(4像素),评测情况(12像素),相邻两个部分之间由1像素的分隔线“ | ”分开。其中,排名右对齐显示,队名左对齐显示,长度不足时用空格补齐。题号一定是4位正整数,因此恰好占据4像素。评测情况则比较复杂,它由两侧的括号 [ ] 以及中间10像素组成。
数据范围:1 <=T <= 1000 1 <= rank <= 400
1<= S <= 16 1001 <= prob <= 1013 1 <= p <= 9

输入样例:

复制代码
    5
    19 qqqqq_University 1001 Running 3
    125 quailty_U_2 1002 WA
    4 quailty_U_3 1003 TLE
    1 quailty_U_4 1003 FB
    2 qqqqq 1001 AC

输出样例:

复制代码
     19|qqqqq_University|1001|[XXX       ]
    125|quailty_U_2     |1002|[    WA    ]
      4|quailty_U_3     |1003|[    TLE   ]
      1|quailty_U_4     |1003|[    AC*   ]
      2|qqqqq           |1001|[    AC    ]

这道题需要注意的点:
① 如果该条评测记录的状态是"Running",需要再输入一个正整数p表示它通过了多少个测试点,输出的评测情况标为p个"X",例如样例1:p = 3,输出为:19|qqqqq_University|1001|[XXX ]
② 注意"Running"的判断条件,因为评测情况里还包含一个"RTE",不能只判断第一个字符"R"。

思路采用模拟的方式;较为便捷的方式是利用C++语言的输出控制语句;同时还可以通过手动的方式进行模拟;只要遵循相应的格式规范即可。

ac代码:

复制代码
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h> 
    #include <string>//学习<strng.h>与<string>两个头文件的区别 
    #include <algorithm>
    #include <vector>
    #include <iomanip> 
    using namespace std;
    //学习使用C++输出的格式控制 
     
    int main()
    {
    	int T, rank, prob, p;
    	string sname, status;
    	cin>>T;
    	while(T--)
    	{
    		cin>>rank>>sname>>prob>>status;
    		if(status[0] == 'R' && status[1] == 'u')
    		{
    			status = "";
    			cin>>p;
    			for(int i = 1; i <= p; i++)
    				status += 'X';
    		}
    		else if(status[0] == 'F')
    			status = "AC*";
    		cout<<right<<setw(3)<<rank<<"|";
    		cout<<left<<setw(16)<<sname<<"|";
    		cout<<prob<<"|[";
    		if(status[0] == 'X')
    			cout<<left<<setw(10)<<status<<"]"<<endl;
    		else cout<<"    "<<left<<setw(6)<<status<<"]"<<endl;
    	}
    	
    	return 0;
    }

全部评论 (0)

还没有任何评论哟~