A.Ascending Rating HDU - 6319
这道题需要用到单调队列,然后结论是,区间[l,r]中,要反着push(a[i]),从r到l,然后此时deque.size()就是count,deque.front()就是maxrating。
#include<deque>
#include<iostream>
#include<queue>
#include<stack>
#define ll long long
using namespace std;
ll n, m, k, q, p, r, mod, t;
const int maxn = 1e7 + 50;
ll a[maxn];
deque<ll> d;
void push_in(ll x) {
if (d.empty())
d.push_back(x);
else if ((!d.empty()) && x >= d.back()) {
while ((!d.empty())&&x >= d.back())d.pop_back();//这里注意,empty一定要写,并且要写在前面
d.push_back(x);
}
else d.push_back(x);
}
int main() {
ios::sync_with_stdio(false);
cin >> t;
while (t--) {
d.clear();
ll suma = 0, sumb = 0;
ll maxrating = -1, cnt = 0;
cin >> n >> m >> k >> p >> q >> r >> mod;
for (ll i = 1; i <= k; i++) {
cin >> a[i];
}
for (ll i = k + 1; i <= n; i++) {
a[i] = (p*a[i - 1] + q * i + r) % mod;
}
ll pos = n - m + 1;
for (ll i = n; i>n - m; i--) {
push_in(a[i]);
}
suma += (d.front() ^ pos);
sumb += (d.size() ^ pos);
pos--;
ll j = n;
for (ll i = pos; i>0; i--, j--) {
if (a[j] == d.front())d.pop_front();
push_in(a[i]);
suma += (d.front() ^ i);
sumb += (d.size() ^ i);
}
cout << suma << " " << sumb << endl;
//system("pause");
}
}
C.Dynamic Graph Matching HDU - 6321
这个题要用状压dp,dp[now] [s] 表示当前状态now中集合数为s的匹配数,然后就是神仙推出来的转移方程了
加一条边的时候:dp[now] [i] [((1<<from)|(1<<to))] += dp[pre] [i];
减一条边的时候:dp[now] [i] [((1<<from)|(1<<to))] -= dp[pre] [i];
#include <bits/stdc++.h>
#define maxn 2005
using namespace std;
const int mod=1e9+7;
int dp[2][maxn];///用滚动数组压缩
int cnt[maxn];
int ans[maxn];
char str[2];
int bit(int x){//获取某个数二进制位上有多少个1
int cnt=0;
while(x){
if(x&1) cnt++;
x>>=1;
}
return cnt;
}
void init(){//初始化处理二进制位上1的个数
for(int i=0;i<1024;i++){
cnt[i]=bit(i);
}
}
int main()
{
int t;
scanf("%d",&t);
init();
while(t--){
int n,m;int now=1,pre=0;
scanf("%d%d",&n,&m);
int all=1<<n;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
while(m--){
scanf("%s",str);
int from,to;
scanf("%d%d",&from,&to);
from--,to--;
int tmp=(1<<from)|(1<<to);//代表第from位和第to位有一条边
for(int i=0;i<all;i++){//先进行状态转移
dp[now][i]=dp[pre][i];
}
if(str[0]=='+'){
for(int i=0;i<all;i++){
if(!(tmp&i)){//如果没加上
dp[now][i|tmp]=(dp[now][i|tmp]+dp[pre][i])%mod;
}
}
}
else{
for(int i=0;i<all;i++){
if(!(tmp&i)){//如果没减去
dp[now][i|tmp]=(dp[now][i|tmp]-dp[pre][i]+mod)%mod;
}
}
}
memset(ans,0,sizeof(ans));
for(int i=0;i<all;i++){//统计答案
ans[cnt[i]]=(ans[cnt[i]]+dp[now][i])%mod;
}
for(int i=2;i<=n;i+=2){///一个匹配数需要2个点
if(i!=2) cout<<" ";
cout<<ans[i];
}
puts("");
// printf("%d %d\n",pre,now);
pre^=1,now^=1;
// printf("%d %d\n",pre,now);
}
}
}
D.Euler Function HDU - 6322
结论:7及以上的结果是连着了,前面一个5。
#include<iostream>
using namespace std;
#define ll long long
ll n,x;
int main(){
cin>>n;
while(n--){
cin>>x;
if(x==1){
cout<<5<<endl;
continue;
}
else cout<<x+5<<endl;
}
}
F.Grab The Tree HDU - 6324
因为是异或,所以还是比较好想,当二进制的最高位有奇数个时,Q一定赢,以此类推,可以得到结论:当所有的节点异或起来得到sum==0时,才会是平局,其他情况都是Q赢。
#include<iostream>
using namespace std;
int n,t,x,y,flag,val,temp;
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
int sum=0;
flag=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>val;
sum=sum^val;
}
for(int i=1;i<n;i++){
cin>>x>>y;
}
if(sum==0)cout<<"D"<<endl;
else cout<<"Q"<<endl;
}
}
L.Visual Cube HDU - 6330
没什么好说的,直接模拟
#include<iostream>
using namespace std;
int t,a,b,c;
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>a>>b>>c;
int len=(b+c)*2+1;
int lenw=(a+b)*2+1;
for(int i=0;i<len;i++,cout<<endl){
int pos=0;
if(i<2*b){
for(int j=i;j<2*b;j++,pos++)cout<<'.';
for(int j=0;j<a;j++,pos+=2){
if(i%2==0)cout<<"+-";
else cout<<"/.";
}
}
if(i>=2*b){
for(int j=0;j<a;j++,pos+=2){
if(i%2==0)cout<<"+-";
else cout<<"|.";
}
}
if(i<=2*c){
for(int j=pos;j<lenw;j++){
if(i%2==0){
if(j%2==0)cout<<'+';
else cout<<'.';
}else {
if(j%2==0)cout<<'|';
else cout<<'/';
}
}
}
if(i>2*c){
for(int j=pos;j<lenw-(i-2*c);j++){
if(i%2==0){
if(j%2==0)cout<<'+';
else cout<<'.';
}else {
if(j%2==0)cout<<'|';
else cout<<'/';
}
}
for(int j=0;j<i-2*c;j++)
cout<<'.';
}
}
}
}